如果我们使用 React Redux Hooks,我们如何实现代码重用?
How to we achieve code-reuse if we use React Redux Hooks?
假设我们有一个组件:
function Count() {
const count = useSelector(state => state.count);
const dispatch = useDispatch();
const increment = () => dispatch({ type: 'INCREMENT' });
const decrement = () => dispatch({ type: 'DECREMENT' });
return (
<div>
<button onClick={increment}> + </button>
{count}
<button onClick={decrement}> - </button>
</div>
);
}
假设它实际上是一个复杂的组件,而不是 return ()
中的 3 行代码,而是 45 或 80 行代码。那么,如果我们需要将这个组件映射到不同的 Redux 状态,如果我们不想重复代码,我们如何实现代码重用?
例如,
- 如果我们在同一页面上需要两个这样的组件,一个用于
countIceCream
,一个用于 countDrink
,该怎么办?
- 如果在 To Go Order 页面上,我们需要这样的组件,但它用于
countSpoon
?
我要做的是
制作两个组件,第一个 IceCreamCount
或 DrinkCount
第二个是基本的 Count
组件,不会连接到 redux
示例:
function Count(props){
return (
<div>
<button onClick={props.increment}> + </button>
{props.count}
<button onClick={props.decrement}> - </button>
</div>
);
}
//connected to redux
function IceCreamCount(props){
return <Count count={props.count} increment={...} decrement={...} />
}
如果我理解正确的话,您希望生成相同的输出,但从不同位置获取 CountIceCream 和 CountDrink 的状态数据。 CountIceCream 和 CountDrink 的操作也不同。
下面是 CountIceCream 和 CountDrink 的增量操作示例:
const incrementDrink = ()=>({type;INCREMENT_DRINK})
const incrementIceCream = ()=>({type;INCREMENT_ICE_CREAM})
这里是获取饮料和冰淇淋计数数据的选择器(这是一个简单的例子,在项目中我建议使用 composable selectors 来防止重复)
const selectIceCreamCount = state => state.iceCream.count;
const selectIceDrinkCount = state => state.drinkCream.count;
您的容器可能如下所示:
const CounterContainer = function CounterContainer(
{ selector, up, down, remove },
props
) {
const dispatch = useDispatch();
const count = useSelector(selector);
const propsForPresentational = {
count
increment: () => dispatch(incement),
decrement: () => dispatch(decrement),
...props,
};
//a container should not return jsx,
// better create a presentational component instead
return <div>bunch of jsx</div>
};
以下是创建冰淇淋计数容器的方法:
export const IceCreamCountContainer = React.memo(
function IceCreamCountContainer(props) {
return CounterContainer(
{
selector: selectIceCreamCount,
increment:incrementIceCream,
decrement:decrementIceCream,
},
props
);
}
);
假设我们有一个组件:
function Count() {
const count = useSelector(state => state.count);
const dispatch = useDispatch();
const increment = () => dispatch({ type: 'INCREMENT' });
const decrement = () => dispatch({ type: 'DECREMENT' });
return (
<div>
<button onClick={increment}> + </button>
{count}
<button onClick={decrement}> - </button>
</div>
);
}
假设它实际上是一个复杂的组件,而不是 return ()
中的 3 行代码,而是 45 或 80 行代码。那么,如果我们需要将这个组件映射到不同的 Redux 状态,如果我们不想重复代码,我们如何实现代码重用?
例如,
- 如果我们在同一页面上需要两个这样的组件,一个用于
countIceCream
,一个用于countDrink
,该怎么办? - 如果在 To Go Order 页面上,我们需要这样的组件,但它用于
countSpoon
?
我要做的是
制作两个组件,第一个 IceCreamCount
或 DrinkCount
第二个是基本的 Count
组件,不会连接到 redux
示例:
function Count(props){
return (
<div>
<button onClick={props.increment}> + </button>
{props.count}
<button onClick={props.decrement}> - </button>
</div>
);
}
//connected to redux
function IceCreamCount(props){
return <Count count={props.count} increment={...} decrement={...} />
}
如果我理解正确的话,您希望生成相同的输出,但从不同位置获取 CountIceCream 和 CountDrink 的状态数据。 CountIceCream 和 CountDrink 的操作也不同。
下面是 CountIceCream 和 CountDrink 的增量操作示例:
const incrementDrink = ()=>({type;INCREMENT_DRINK})
const incrementIceCream = ()=>({type;INCREMENT_ICE_CREAM})
这里是获取饮料和冰淇淋计数数据的选择器(这是一个简单的例子,在项目中我建议使用 composable selectors 来防止重复)
const selectIceCreamCount = state => state.iceCream.count;
const selectIceDrinkCount = state => state.drinkCream.count;
您的容器可能如下所示:
const CounterContainer = function CounterContainer(
{ selector, up, down, remove },
props
) {
const dispatch = useDispatch();
const count = useSelector(selector);
const propsForPresentational = {
count
increment: () => dispatch(incement),
decrement: () => dispatch(decrement),
...props,
};
//a container should not return jsx,
// better create a presentational component instead
return <div>bunch of jsx</div>
};
以下是创建冰淇淋计数容器的方法:
export const IceCreamCountContainer = React.memo(
function IceCreamCountContainer(props) {
return CounterContainer(
{
selector: selectIceCreamCount,
increment:incrementIceCream,
decrement:decrementIceCream,
},
props
);
}
);