useState & useReducer

2022-02-28  本文已影响0人  Yandhi233

useState

在 React 函数组件中存储内部 state 通常会使用 useState hook 传入一个初始值,在初次渲染时创建 state,之后会返回当前的 state。

const [state, setState] = useState(initialState)

下面是一个点击+1的 demo

function App() {
  const [n, setN] = useState(0);
  return (
    <div className="App">
      <p>{n}</p>
      <p>
        <button onClick={() => setN(n + 1)}>+1</button>
      </p>
    </div>
  )
}

实现一个简单的 useState

let state
const myUseState = (initialState) => {
    state = state === undefined ? initialState : state
    const setState = (newState) => {
        state = newState
        // 执行渲染函数
    }
    return [state, setState]
}

这样写组件只能初始化一个变量,如果有多个怎么办?

let state = []
let index = 0  // 使用 index 来记录组件内 useState 顺序
const myUseState = (initialState) => {
    let currentIndex = index
    state[currentIndex ] = state[currentIndex ] === undefined ? initialState : state[currentIndex ]
    const setState = (newState) => {
        state[currentIndex ] = newState
        index = 0  // 重置 index
        // 执行渲染函数
    }
    index++  
    return [state[currentIndex ], setState]
 }

每次组件渲染,执行 myUseState,如果没有触发 setState 函数,则会将初始值赋值给 state,执行 setState 后组件会再此渲染一次,此时 产生一个新的 state,值为 newState,然后将这个新的 state 返回。所以,setState 并不会改变原有的 state,而是产生一个新的 state。

如果组件内有多个 useState

useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init);

useReducer 接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其对应的 dispatch 方法;

如果 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 时,useReducer 比 useState 更加适用。

const initialState = {n: 0}
const reducer = (state, action) => {
  switch (action.type) {
    case '+':
        return {n: state.n + 1};
    case '-':
        return {n: state.n - 1};
    default:
      alert('unknow type')
      break;
  }
}
function App() {
  const [state, dispatch] = useReducer(reducer, initialState)
  return (
    <div className="App">
      <h1>n: {state.n}</h1>
      <button onClick={() => dispatch({type: '+'})}>+1</button>
      <button onClick={() => dispatch({type: '-'})}>-1</button>
    </div>
  );
}

使用 useReducer 步骤:

上一篇 下一篇

猜你喜欢

热点阅读