useReducer 不同步更新状态的问题

You*_*sef 8 javascript reactjs

根据React文档:

当您具有涉及多个子值的复杂状态逻辑或下一个状态取决于前一个状态时,useReducer 通常比 useState 更可取。

1.有人能解释一下为什么useReducer不同步更新状态吗?

const reducer = (state, action) => {
    if( action.type === 'ADD_VALUE') {
        console.log(`STATE IN REDUCER`, [...state, action.path]) // => ["1.1"]
        return [...state, action.path]
    }   
}

const [state, dispatch] = useReducer(reducer, [])

<input type="button" onClick={() => {
    dispatch({ type: 'ADD_VALUE', path: "1.1"})
    console.log(`STATE`, state) // => []
    // here i want to do some stuff based on the lastest updated state (["1.1"] and not [])
    // for example dispatch an action with redux
}}/>
Run Code Online (Sandbox Code Playgroud)

2.我怎样才能根据最新更新的状态(["1.1"]而不是[])做一些事情(调度一个 redux 动作)?

Win*_*Win 8

用于useEffect正确访问状态。如果您希望在达到某个标准时调用某些内容,则可以添加一些安全保护。

如果你想跨组件访问你的 reducer,你可以使用 Context API 存储 reducer。请看下面的示例。您可以看到 reducer 被注入到父组件的 Context 中,然后是两个子组件,它们 a) 分派动作 b) 从动作接收更新。

1. 跨多个组件使用的上下文缩减器示例

import React from "react";
import ReactDOM from "react-dom";

const Application = React.createContext({
  state: null,
  dispatch: null
});

function ActionComponent() {
  const { dispatch } = React.useContext(Application);
  return (
      <div>
          <div>Action Component</div>
          <button onClick={() => dispatch("lol")}>Do something</button>
      </div>
  );
}

function ListenerComponent() {
  const { state } = React.useContext(Application);
  React.useEffect(
    () => {
      console.log(state);
    },
    [state]
  );
  return <div>Listener Component</div>;
}

function App() {
  const [state, dispatch] = React.useReducer(function(state = [], action) {
    return [...state, action];
  });
  return (
    <Application.Provider value={{ state, dispatch }}>
      <div className="App">
        <ActionComponent />
        <ListenerComponent />
      </div>
    </Application.Provider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Run Code Online (Sandbox Code Playgroud)

2. 不使用Application Context的local reducer示例

const reducer = (state, action) => {
    if( action.type === 'ADD_VALUE') {
        return [...state, action.path]
    }   
}

const [state, dispatch] = useReducer(reducer, [])

React.useEffect(() => {
    console.log(state);
}, [state]);

<input type="button" onClick={() => {
    dispatch({ type: 'ADD_VALUE', path: "1.1"})
}}/>
Run Code Online (Sandbox Code Playgroud)