使用 useReducer 从一个子组件分派操作并在另一个子组件中更新状态
Using useReducer to dispatch action from one child component and update state in another child component
这是一个包含以下示例代码的 CodeSandbox,linter 突出显示了一些问题:https://codesandbox.io/s/react-repl-bw2h1
下面是我正在尝试做的一个基本示例。在容器组件中,我有一个上下文 AppContext
为子组件提供状态,<ChildConsumer />
和 <ChildDispatcher />
.
<ChildConsumer />
组件正在使用 useContext
接收此状态,这似乎按预期工作。
在 <ChildDispatcher />
中,我试图在单击按钮时发送一个动作。为此,我创建了一个 reducer reducer
来处理一个动作。我还在此处设置了 useReducer,它接受 reducer
和初始 store
状态。
当我点击按钮时,没有任何反应。我期望发生的是 dispatch
接收从 useReducer
提取的 state
以及一个 action
对象,并将它们传递给减速器。 reducer 应该看到接收到类型为 BUTTON_CLICKED
的操作,并且应该 return 一个包含旧状态的新状态以及一个额外的 'goodbye'
项目。然后,子组件 <ChildConsumer />
应该使用这个新状态重新呈现。
import React, { createContext, useContext, useReducer } from "react";
import ReactDOM from "react-dom";
const store = [""];
const AppContext = createContext(store);
const ChildDispatcher = () => {
const reducer = (state, action) => {
switch (action.type) {
case "BUTTON_CLICKED":
return [...state, "goodbye"];
default:
return state;
}
};
const [state, dispatch] = useReducer(reducer, store);
const handleClick = () =>
dispatch(state, {
type: "BUTTON_CLICKED"
});
return <button onClick={handleClick}>press me</button>;
};
const ChildConsumer = () => {
const [consumer] = useContext(AppContext);
return <div>{consumer}</div>;
};
const App = () => {
return (
<div>
<h1>Using Context and useReducer</h1>
<AppContext.Provider value={["hello"]}>
<ChildConsumer />
<ChildDispatcher />
</AppContext.Provider>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
我对你的代码做了一点小修改。
你必须像下面这样通过调度。 Dispatch 需要一个对象类型的参数。
const handleClick = () => dispatch({ type: "BUTTON_CLICKED" });
然后可以像这样访问这个状态。
const ChildDispatcher = () => {
const reducer = (state, action) => {
switch (action.type) {
case "BUTTON_CLICKED":
//action.state // like this
return [...state, "goodbye"];
default:
return state;
}
};
const [state, dispatch] = useReducer(reducer, store);
const handleClick = () =>
dispatch(state, {
type: "BUTTON_CLICKED"
});
return <button onClick={handleClick}>press me</button>;
};
默认情况下,React 会将状态传递给调度程序。但是如果你想传递一些数据,你可以将它添加到对象中并将该对象传递给调度。
const handleClick = () => dispatch({ type: "BUTTON_CLICKED", state: state });
代码沙盒:
这方面的一些问题:
ChildDispatch状态只对ChildDispatch有效,不会影响上层组件。要更改上下文值,您需要在该组件中提供一个调度并制作一个自定义钩子(或将其作为道具传递)以在 ChildDispatch 中使用它。
调用调度时不要传递状态。 useReducer 会为你处理。发送动作即可。
这就是数据流应该有单向方向的意思。父组件控制共享状态/管理状态的方式,子组件使用它来呈现/执行操作。
这是一个包含以下示例代码的 CodeSandbox,linter 突出显示了一些问题:https://codesandbox.io/s/react-repl-bw2h1
下面是我正在尝试做的一个基本示例。在容器组件中,我有一个上下文 AppContext
为子组件提供状态,<ChildConsumer />
和 <ChildDispatcher />
.
<ChildConsumer />
组件正在使用 useContext
接收此状态,这似乎按预期工作。
在 <ChildDispatcher />
中,我试图在单击按钮时发送一个动作。为此,我创建了一个 reducer reducer
来处理一个动作。我还在此处设置了 useReducer,它接受 reducer
和初始 store
状态。
当我点击按钮时,没有任何反应。我期望发生的是 dispatch
接收从 useReducer
提取的 state
以及一个 action
对象,并将它们传递给减速器。 reducer 应该看到接收到类型为 BUTTON_CLICKED
的操作,并且应该 return 一个包含旧状态的新状态以及一个额外的 'goodbye'
项目。然后,子组件 <ChildConsumer />
应该使用这个新状态重新呈现。
import React, { createContext, useContext, useReducer } from "react";
import ReactDOM from "react-dom";
const store = [""];
const AppContext = createContext(store);
const ChildDispatcher = () => {
const reducer = (state, action) => {
switch (action.type) {
case "BUTTON_CLICKED":
return [...state, "goodbye"];
default:
return state;
}
};
const [state, dispatch] = useReducer(reducer, store);
const handleClick = () =>
dispatch(state, {
type: "BUTTON_CLICKED"
});
return <button onClick={handleClick}>press me</button>;
};
const ChildConsumer = () => {
const [consumer] = useContext(AppContext);
return <div>{consumer}</div>;
};
const App = () => {
return (
<div>
<h1>Using Context and useReducer</h1>
<AppContext.Provider value={["hello"]}>
<ChildConsumer />
<ChildDispatcher />
</AppContext.Provider>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
我对你的代码做了一点小修改。
你必须像下面这样通过调度。 Dispatch 需要一个对象类型的参数。
const handleClick = () => dispatch({ type: "BUTTON_CLICKED" });
然后可以像这样访问这个状态。
const ChildDispatcher = () => {
const reducer = (state, action) => {
switch (action.type) {
case "BUTTON_CLICKED":
//action.state // like this
return [...state, "goodbye"];
default:
return state;
}
};
const [state, dispatch] = useReducer(reducer, store);
const handleClick = () =>
dispatch(state, {
type: "BUTTON_CLICKED"
});
return <button onClick={handleClick}>press me</button>;
};
默认情况下,React 会将状态传递给调度程序。但是如果你想传递一些数据,你可以将它添加到对象中并将该对象传递给调度。
const handleClick = () => dispatch({ type: "BUTTON_CLICKED", state: state });
代码沙盒:
这方面的一些问题:
ChildDispatch状态只对ChildDispatch有效,不会影响上层组件。要更改上下文值,您需要在该组件中提供一个调度并制作一个自定义钩子(或将其作为道具传递)以在 ChildDispatch 中使用它。
调用调度时不要传递状态。 useReducer 会为你处理。发送动作即可。
这就是数据流应该有单向方向的意思。父组件控制共享状态/管理状态的方式,子组件使用它来呈现/执行操作。