useState

不会改变原有值,每回返回一个新的数组,第一个参数读,第二个参数写(是一个函数)
image.png

  1. import React, { useState } from 'react';
  2. function Example() {
  3. // 声明一个新的叫做 “count” 的 state 变量
  4. const [count, setCount] = useState(0);
  5. return (
  6. <div>
  7. <p>You clicked {count} times</p>
  8. <button onClick={() => setCount(count + 1)}>
  9. Click me
  10. </button>
  11. </div>
  12. );
  13. }

useEffect

接受一个函数和一个数组,数组如果不写就是每回调用,[]等于第一次调用
[]里是哪个参数就在哪个参数变化时调用
在函数里面return一个新数组等于消亡时调用

  1. import React, { useState, useEffect } from 'react';
  2. function Example() {
  3. const [count, setCount] = useState(0);
  4. // Similar to componentDidMount and componentDidUpdate:
  5. useEffect(() => {
  6. // Update the document title using the browser API
  7. document.title = `You clicked ${count} times`;
  8. });
  9. useEffect(() => {
  10. // Update the document title using the browser API
  11. document.title = `You clicked ${count} times`;
  12. },[count]);
  13. return (
  14. <div>
  15. <p>You clicked {count} times</p>
  16. <button onClick={() => setCount(count + 1)}>
  17. Click me
  18. </button>
  19. </div>
  20. );
  21. }

useRef

useRef是一个对象里面只有一个current值
image.png

  1. 对一个div的引用
  2. const container = useRef(null)
  3. container.current.style.color = 'white'
  4. return(
  5. <div ref={container} >hi</div>
  6. )

forwardRef

组件里传递props是无法传递ref的,可以用forwardRef把组件包裹起来,箭头函数的参数传入ref即可

  1. function App() {
  2. const buttonRef = useRef(null);
  3. return (
  4. <div className="App">
  5. <Button2 ref={buttonRef}>按钮</Button2>
  6. {/* 看浏览器控制台的报错 */}
  7. </div>
  8. );
  9. }
  10. //const Button2 = props => {
  11. // return <button className="red" {...props} />;
  12. //};
  13. const Button2 = (props, ref) =>{
  14. return <button ClassName="red" ref={ref} {...props}/>
  15. }
  16. const x = React.forwardRef(Button2)

useContext

相当于一个局部的全局变量链接
image.png

  1. //const MyContext = React.createContext(defaultValue);
  2. const x = React.createContext(null)
  3. const [theme,setTheme] = useState("red")
  4. function App(){
  5. <x.provider value={{theme,setTheme}}>
  6. <Child>
  7. ...
  8. </x.provider>
  9. }
  10. function Child(){
  11. const {setTheme} = useContext(x)
  12. <button onClick(()=>{setTheme("blue")})>color</button>
  13. }
  14. <MyContext.Provider value={/* 某个值 */}>

每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。
Provider 接收一个 value 属性,传递给消费组件。一个 Provider 可以和多个消费组件有对应关系。多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据。
当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。从 Provider 到其内部 consumer 组件(包括 .contextType 和 useContext)的传播不受制于 shouldComponentUpdate 函数,因此当 consumer 组件在其祖先组件跳过更新的情况下也能更新。

useReducer

先创建初始值init
创建所有操作reducer(state,action)
传给useReducer,得到读和写接口
调用 写 ({type:操作类型})

  1. const initial = {
  2. n: 0
  3. };
  4. const reducer = (state, action) => {
  5. if (action.type === "add") {
  6. return { n: state.n + action.number };
  7. } else if (action.type === "multi") {
  8. return { n: state.n * 2 };
  9. } else {
  10. throw new Error("unknown type");
  11. }
  12. };
  13. function App() {
  14. const [state, dispatch] = useReducer(reducer, initial);
  15. const { n } = state;
  16. const onClick = () => {
  17. dispatch({ type: "add", number: 1 });
  18. };
  19. const onClick2 = () => {
  20. dispatch({ type: "add", number: 2 });
  21. };
  22. return (
  23. <div className="App">
  24. <h1>n: {n}</h1>
  25. <button onClick={onClick}>+1</button>
  26. <button onClick={onClick2}>+2</button>
  27. </div>
  28. );
  29. }

用来代替Redux

将所有数据集中在一个store里面
将所有操作集中在reducer里
创建一个Context
创建对函数读写的API
将第四步的内容放到第三步的Context
用Context.Provider将Context提供给所有组件
各个组件使用Context获取读写API

  1. const store = {
  2. user: null,
  3. books: null,
  4. movies: null
  5. };
  6. function reducer(state, action) {
  7. switch (action.type) {
  8. case "setUser":
  9. return { ...state, user: action.user };
  10. case "setBooks":
  11. return { ...state, books: action.books };
  12. case "setMovies":
  13. return { ...state, movies: action.movies };
  14. default:
  15. throw new Error();
  16. }
  17. }
  18. const Context = React.createContext(null);
  19. function App() {
  20. const [state, dispatch] = useReducer(reducer, store);
  21. const api = { state, dispatch };
  22. return (
  23. <Context.Provider value={api}>
  24. <User />
  25. <hr />
  26. <Books />
  27. <Movies />
  28. </Context.Provider>
  29. );
  30. }
  31. function User() {
  32. const { state, dispatch } = useContext(Context);
  33. useEffect(() => {
  34. ajax("/user").then(user => {
  35. dispatch({ type: "setUser", user: user });
  36. });
  37. }, []);
  38. return (
  39. <div>
  40. <h1>个人信息</h1>
  41. <div>name: {state.user ? state.user.name : ""}</div>
  42. </div>
  43. );
  44. }
  45. function Books() {
  46. const { state, dispatch } = useContext(Context);
  47. useEffect(() => {
  48. ajax("/books").then(books => {
  49. dispatch({ type: "setBooks", books: books });
  50. });
  51. }, []);
  52. return (
  53. <div>
  54. <h1>我的书籍</h1>
  55. <ol>
  56. {state.books ? state.books.map(book => <li key={book.id}>{book.name}</li>) : "加载中"}
  57. </ol>
  58. </div>
  59. );
  60. }
  61. function Movies() {
  62. const { state, dispatch } = useContext(Context);
  63. useEffect(() => {
  64. ajax("/movies").then(movies => {
  65. dispatch({ type: "setMovies", movies: movies });
  66. });
  67. }, []);
  68. return (
  69. <div>
  70. <h1>我的电影</h1>
  71. <ol>
  72. {state.movies
  73. ? state.movies.map(movie => <li key={movie.id}>{movie.name}</li>)
  74. : "加载中"}
  75. </ol>
  76. </div>
  77. );
  78. }

useMemo

减少多余的render
App里面的Child组件不需要再次执行可以用React.memo包起来
如果子组件了里面添加的监听事件触发则不行,需要改为useMemo即可

  1. function App() {
  2. const [n, setN] = React.useState(0);
  3. const [m, setM] = React.useState(0);
  4. const onClick = () => {
  5. setN(n + 1);
  6. };
  7. return (
  8. <div className="App">
  9. <div>
  10. <button onClick={onClick}>update n {n}</button>
  11. </div>
  12. <Child data={m}/>
  13. {/* <Child2 data={m}/> */}
  14. </div>
  15. );
  16. }
  17. function Child(props) {
  18. console.log("child 执行了");
  19. ...
  20. console.log('执行代码')
  21. return <div>child: {props.data}</div>;
  22. }
  23. const Child2 = React.memo(Child);

useMemo return返回一个函数,语法糖可以改写为useCallback

  1. const ChildEvent = useMemo(()=>{
  2. return ()=>{
  3. console.log('xxx')
  4. }
  5. })
  6. const ChildEvent = useCallback(()=>{
  7. console.log('xxx')
  8. })