在最初的问题中我从未明确表示清楚,但是我正在尝试在没有Redux的情况下完成所有这些操作,这意味着没有useSelector();。
这是仅使用本机React来实现选择器的练习。
我正在尝试使用钩子来构建类似Redux的安排,我是borrowing heavily from this guy
因此,我们有一家商店:
const CarStore = ({ children }) => {
const [state, dispatch] = useReducer(
carReducer,
[
{
type: 'fast',
mpg: 'bad',
},
],
);
return (
<CarStateContext.Provider value={selectors}>
<CarDispatchContext.Provider value={dispatch}>
{children}
</CarDispatchContext.Provider>
</CarStateContext.Provider>
);
};
export const CarStateContext = createContext();
export const CarDispatchContext = createContext();
现在,dispatch
可以通过state
自动访问carReducer
,这非常好。即时Redux!
无论如何,Redux的一半。我仍然缺少选择器,这就是我的问题。在上述情况下,如何最好地构建一个像getCarType()
这样的选择器,该选择器将“快速”返回给组件?
一个模糊的想法可能是这样的:
const CarStore = ({ children }) => {
const [state, dispatch] = useReducer(
carReducer,
[
{
type: 'fast',
mpg: 'bad',
},
],
);
// selectors, kind of.
const selectors = {
getType: () => { return state.type; },
getMpg: () => { return state.mpg; },
};
return (
<CarStateContext.Provider value={selectors}> // <- don't return state, return selectors
<CarDispatchContext.Provider value={dispatch}>
{children}
</CarDispatchContext.Provider>
</CarStateContext.Provider>
);
};
export const CarStateContext = createContext();
export const CarDispatchContext = createContext();
我猜这确实有效,但是可能有更好的解决方案?
答案 0 :(得分:3)
这里最好的通用解决方案是提供一个由redux提供的名为useSelector
的简单API,该API接受回调并以当前状态进行调用并返回结果。
const CarStore = ({ children }) => {
const [state, dispatch] = useReducer(
carReducer,
[
{
type: 'fast',
mpg: 'bad',
},
],
);
const useSelector = (callback) => {
return callback(state)
};
return (
<CarStateContext.Provider value={{useSelector}}> // <- don't return state, return selectors
<CarDispatchContext.Provider value={dispatch}>
{children}
</CarDispatchContext.Provider>
</CarStateContext.Provider>
);
};
export const CarStateContext = createContext();
export const CarDispatchContext = createContext();
完成此操作后,您就可以将其用于任何组件
const Comp = () => {
const {useSelector} = useContext(CarStateContext);
const type = useSelector((state) => { return state.type; })
const mpg = useSelector((state) => { return state.mpg; })
}
EDIT-方法2:在上述情况下,您需要分别使用useContext
和useSelector
来避免这种情况,您也可以将useSelector实现为一个钩子。另外,您不需要两个单独的上下文来进行调度和状态,您可以只使用一个
const CarStore = ({ children }) => {
const [state, dispatch] = useReducer(
carReducer,
[
{
type: 'fast',
mpg: 'bad',
},
],
);
const getValue = (callback) => {
return callback(state)
};
return (
<CarStateContext.Provider value={{getValue, dispatch}}> // <- don't return state, return selectors
{children}
</CarStateContext.Provider>
);
};
export const CarStateContext = createContext();
export const useSelector = (callback) => {
const {getValue} = useContext(CarStateContext);
return getValue(callback)
}
// Similarly dispatch can be provided like below
export const useDispatch = () => {
const {dispatch} = useContext(CarStateContext);
return dispatch
}
并在您的组件中使用它,例如
import { useSelector, useDispatch } from 'path/to/useSelector'
const Comp = () => {
const type = useSelector((state) => { return state.type; })
const mpg = useSelector((state) => { return state.mpg; })
const dispatch = useDispatch();
}