gpt4 book ai didi

javascript - 如何将 React Context 中的值传递给 Redux-Saga 函数?

转载 作者:行者123 更新时间:2023-12-02 01:51:32 25 4
gpt4 key购买 nike

如何将 React 上下文中的内容传递到我的 Redux Saga 函数中?

我有一个上下文值,我可以用这样的东西在 react 组件中检索

const { connectionObject } = useMyContext();

这将允许我从上下文中获取 connectionObject 实例。

但是,我还在应用程序的其他部分使用了 redux saga。其中一个 redux sagas 需要使用上下文中的 personObject

由于 Redux-Sagas 本身在技术上只是常规生成器函数,所以我不能在其中使用 useMyContext() 来检索 connectionObject。例如,这是行不通的

export function* saveData() {
const { connectionObject } = useMyContext(); // This will not work
yield performSaveSomething(connectionObject);
}

Redux Saga 是由我从 React 组件中调度一个 redux Action 触发的。一种可能的解决方法当然是从 React 组件的上下文中获取 connectionObject,然后使用 connectionObject 分派(dispatch)操作作为有效负载的一部分,然后将其传递给传奇。但这感觉完全反模式并且不优雅,尤其是当有效负载应该更新为状态但在这种情况下仅用于传递给传奇时。这是一个说明尴尬的例子:

// In the React component
export const myReactComponent = (props) => {
const { connectionObject } = useMyContext();
dispatch(saveDataAction({
data: 'some data here to be put in the redux store',
connection: connectionObject
}));
}

// In the reducer
function reducer (state, action) {
switch (action.type) {
case SAVE_DATA_ACTION_TYPE:
// action.payload has 2 attributes in this case: data and connection
// But I am throwing away the connection one here in this reducer because that is only meant for the saga. Feels weird here.
return {
...state,
data: action.payload.data. // Instead of using the whole payload, I've to use only the "data" attribute of the payload because only this mattered to the store. I can't use the whole payload because it has the connectionObject in there. Doesn't look elegant.
}
}
}

// And finally in the saga function
export function* saveData({ payload: { connection } }) {
// Good thing here is I could finally access the connectionObject which came from the react context
// However, it's also doesn't seem right that I'm passing the connectionObject through the payload which isn't a piece of data but as a dependency
yield performSaveSomething(connection);
}

有没有一种方法可以让我优雅而轻松地传递从 React 上下文中检索到的值,并以某种方式将它传递到我的 Redux-Saga 函数中,以便它可以使用它?

最佳答案

我的第一个倾向是按照您的建议进行操作:将其包含在操作的有效负载中。组件知道值,saga 需要值,因此它可以将值传入。这可能是最简单的解决方案。

除此之外……这有点取决于上下文值的性质。让我们从最简单的案例开始,然后转向更难的案例。最简单的情况:上下文只有一个副本,它的值永远不会改变。如果它永远不会改变,那么它实际上不需要在上下文中。您只需将 connectionObject 移动到一个文件中,将其导出,然后将其导入到任何需要的地方。


但是您正在使用上下文,所以它可能是一个确实发生变化的值。所以这将我们带到下一个案例:只有一个副本,它的值确实改变了,但只有组件在它改变时关心(传奇只会在需要时查找它,而不需要是通知)。为此,我可能会让上下文提供程序将其状态复制到一个全局变量中,传奇会检查该变量。

let globalValue = {};
export const getGlobalValue = () => globalValue;

export const MyContextProvider = ({ children }) => {
const [stateValue, setStateValue] = useState({});
useEffect(() => {
globalValue = stateValue;
}, [stateValue]);

return (
<MyContext.Provider value={stateValue}>
{children}
</MyContext.Provider>
)
}

// In the saga:
import { getGlobalValue } from './path/to/context/provider/file'

export function* saveData() {
const connectionObject = getGlobalValue();
yield performSaveSomething(connectionObject);
}

下一个困难是只有一个副本,值发生变化,组件和 sagas 都需要能够监听其值的变化。例如,可能 saga 开始,检查值,如果它发现值是假的,它需要休眠直到值变为真。

为了支持这一点,您需要有某种事件发射器,传奇可以订阅它。有许多用于此类代码的现有库,我们可以推出自己的库,例如:

let listeners = [];
export const subscribe = (callback) => {
listeners.push(callback);
const unsubscribe = () => {
let i = listeners.indexOf(callback);
listeners.splice(i, 1);
}
return unsubscribe;
}

export const MyContextProvider = ({ children }) => {
const [stateValue, setStateValue] = useState({});
useEffect(() => {
for (const listener of [...listeners]) {
callback(stateValue);
}
}, [stateValue]);
// ...
}

最后,最困难的情况:有多个上下文提供者。如果是这种情况,那么就有多个可能的值,而 saga 无法知道使用哪一个。当然,除了告诉它您将通过操作负载执行哪些操作外,别无他法,这会让我们回到最初的想法。

我想可以不传递整个对象,而只传递一个 id,然后使用上面的一种技术来查找对象。但我不认为这比传递对象本身更好。

关于javascript - 如何将 React Context 中的值传递给 Redux-Saga 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70270533/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com