Hook 实现原理请参考 一文彻底搞懂react hooks的原理和实现
前言
对于 react 函数组件,管理组件状态最常用的 hooks 就是useState
。
但在某些场景下,例如需要跨多层组件传递状态,或者组件中状态过多(一堆 useState),react hooks 提供了更优雅的解决方法。
useContext
1、可以用来传递状态和方法(例如修改状态的方法)
2、能够避免多级组件,层层通过 props 来嵌套传递。可以直接在任意组件中直接使用 context。
3、一般将所有的 context 都收归到一个文件夹下进行统一管理,对外暴露提供引用。方便维护和定位问题。
下面的代码是在子组件中使用状态,并且调用上级组件状态更新方法,触发状态更新:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
|
import React, { useReducer, createContext, useContext, useState } from "react"; import ReactDOM from "react-dom";
const UserContext = createContext({});
const App = () => { const [name, setName] = useState("xin-tan"); const [age, setAge] = useState(22);
return ( <UserContext.Provider value={{ name, age, setAge, setName }}> <div style={{ cursor: "pointer" }} onClick={() => { setAge(age + 1); }} > (APP组件)点我增加年龄 </div> <hr></hr> <B /> </UserContext.Provider> ); };
const B = () => { return <C />; };
const C = () => { const { age, setAge } = useContext(UserContext);
return ( <> <div>姓名:{name}</div> <div>年龄:{age}</div> <div style={{ cursor: "pointer" }} onClick={() => { setAge(age + 1); }} > (C组件)点我增加年龄 </div> </> ); };
const rootElement = document.getElementById("app"); ReactDOM.render(<App />, rootElement);
|
useReducer
useReducer 和 redux 的使用基本一致:
1、返回中有 state,上面挂着状态
2、Reducer 用来执行状态更新
3、通过 dispatch 来发起状态更新
4、useReducer 的第三个参数接受一个函数作为参数,并把第二个参数当作函数的参数执行,返回的值作为初始值
下面是 useReducer 的使用案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
import React, { useReducer } from "react"; import ReactDOM from "react-dom";
const initialState = { count: 0, };
function reducer(state, action) { switch (action.type) { case "increment": return { count: state.count + action.payload }; case "decrement": return { count: state.count - action.payload }; default: throw new Error(); } }
function App() { const [state, dispatch] = useReducer(reducer, initialState); const [state2, dispatch2] = useReducer(reducer, initialState); return ( <div> Count: {state.count} <button onClick={() => dispatch({ type: "increment", payload: 5 })}> + </button> <button onClick={() => dispatch({ type: "decrement", payload: 5 })}> - </button> Count2: {state2.count} <button onClick={() => dispatch2({ type: "increment", payload: 5 })} > + </button> <button onClick={() => dispatch2({ type: "decrement", payload: 5 })}>-</button> </div> ); }
const rootElement = document.getElementById("app"); ReactDOM.render(<App />, rootElement);
|
参考链接