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 也可以嵌套使用,里层的会覆盖外层的数据。
Providervalue 值发生变化时,它内部的所有消费组件都会重新渲染。从 Provider 到其内部 consumer 组件(包括 .contextTypeuseContext)的传播不受制于 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. })