我如何创建一个带有参数的辅助方法来过滤来自 redux 存储的数据?
How can I create a helper method that takes a param to filter data from a redux store?
在我的 react/redux/redux-thunk 应用程序中,我有一个 reducer 来管理状态,其中包含类似于以下内容的列表:
state = {
stuff: [
{
id: 1,
color: "blue",
shape: "square"
},
{
id: 2,
color: "red",
shape: "circle"
},
{
id: 3,
color: "yellow",
shape: "square"
},
]
};
我想创建我可以在我的应用程序中使用的辅助函数,根据传递给函数的参数,return 从商店过滤商品列表。例如:
getStuffByShape("square"); // returns array with stuff 1 and 3
getStuffByColor("red"); // returns array with stuff 2
我了解到我可以创建一个单例存储,我可以根据需要将其导入到不同的文件中,但不推荐这样做。我目前没有进行任何服务器端渲染,但我不想在将来限制我的选择。
我读过有关创建选择器和 reselect
包的内容,但示例仅显示了采用状态参数的函数,我不清楚是否可以传入一个额外的任意参数。
我可以将状态作为连接组件的参数传递,但我可能想在其他地方使用这些函数,例如其他辅助函数。
您可以创建一个 parameterized selector,我的首选方法是您可以记忆的咖喱方法:
const { Provider, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const { createSelector } = Reselect;
const initialState = {
stuff: [
{
id: 1,
color: 'blue',
shape: 'square',
},
{
id: 2,
color: 'red',
shape: 'circle',
},
{
id: 3,
color: 'yellow',
shape: 'square',
},
],
};
const reducer = (state) => state;
//helper
const createFilterBy = (field, value) => (item) =>
value ? item[field] === value : true;
//selectors
const selectStuff = (state) => state.stuff;
const createSelectFiltered = (filterFn) =>
createSelector([selectStuff], (stuff) =>
stuff.filter(filterFn)
);
const createSelectByColor = (color) =>
createSelector(
[createSelectFiltered(createFilterBy('color', color))],
(x) => x
);
const createSelectByShape = (shape) =>
createSelector(
[createSelectFiltered(createFilterBy('shape', shape))],
(x) => x
);
//creating store with redux dev tools
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducer,
initialState,
composeEnhancers(
applyMiddleware(() => (next) => (action) =>
next(action)
)
)
);
const List = React.memo(function List({ items }) {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{JSON.stringify(item)}</li>
))}
</ul>
);
});
const SelectList = React.memo(function SelectList({
label,
value,
setter,
options,
}) {
return (
<label>
{label}
<select
value={value}
onChange={({ target: { value } }) =>
setter(value === 'all' ? undefined : value)
}
>
<option value="all">all</option>
{options.map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
</label>
);
});
const colors = ['blue', 'red', 'yellow'];
const shapes = ['square', 'circle'];
const App = () => {
const [color, setColor] = React.useState();
const [shape, setShape] = React.useState();
const selectByColor = React.useMemo(
() => createSelectByColor(color),
[color]
);
const selectByShape = React.useMemo(
() => createSelectByShape(shape),
[shape]
);
const byColor = useSelector(selectByColor);
const byShape = useSelector(selectByShape);
return (
<div>
<div>
<SelectList
label="color"
value={color}
setter={setColor}
options={colors}
/>
<SelectList
label="shape"
value={shape}
setter={setShape}
options={shapes}
/>
</div>
<div>
<h4>color</h4>
<List items={byColor} />
<h4>shape</h4>
<List items={byShape} />
</div>
</div>
);
};
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>
<div id="root"></div>
在我的 react/redux/redux-thunk 应用程序中,我有一个 reducer 来管理状态,其中包含类似于以下内容的列表:
state = {
stuff: [
{
id: 1,
color: "blue",
shape: "square"
},
{
id: 2,
color: "red",
shape: "circle"
},
{
id: 3,
color: "yellow",
shape: "square"
},
]
};
我想创建我可以在我的应用程序中使用的辅助函数,根据传递给函数的参数,return 从商店过滤商品列表。例如:
getStuffByShape("square"); // returns array with stuff 1 and 3
getStuffByColor("red"); // returns array with stuff 2
我了解到我可以创建一个单例存储,我可以根据需要将其导入到不同的文件中,但不推荐这样做。我目前没有进行任何服务器端渲染,但我不想在将来限制我的选择。
我读过有关创建选择器和 reselect
包的内容,但示例仅显示了采用状态参数的函数,我不清楚是否可以传入一个额外的任意参数。
我可以将状态作为连接组件的参数传递,但我可能想在其他地方使用这些函数,例如其他辅助函数。
您可以创建一个 parameterized selector,我的首选方法是您可以记忆的咖喱方法:
const { Provider, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const { createSelector } = Reselect;
const initialState = {
stuff: [
{
id: 1,
color: 'blue',
shape: 'square',
},
{
id: 2,
color: 'red',
shape: 'circle',
},
{
id: 3,
color: 'yellow',
shape: 'square',
},
],
};
const reducer = (state) => state;
//helper
const createFilterBy = (field, value) => (item) =>
value ? item[field] === value : true;
//selectors
const selectStuff = (state) => state.stuff;
const createSelectFiltered = (filterFn) =>
createSelector([selectStuff], (stuff) =>
stuff.filter(filterFn)
);
const createSelectByColor = (color) =>
createSelector(
[createSelectFiltered(createFilterBy('color', color))],
(x) => x
);
const createSelectByShape = (shape) =>
createSelector(
[createSelectFiltered(createFilterBy('shape', shape))],
(x) => x
);
//creating store with redux dev tools
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducer,
initialState,
composeEnhancers(
applyMiddleware(() => (next) => (action) =>
next(action)
)
)
);
const List = React.memo(function List({ items }) {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{JSON.stringify(item)}</li>
))}
</ul>
);
});
const SelectList = React.memo(function SelectList({
label,
value,
setter,
options,
}) {
return (
<label>
{label}
<select
value={value}
onChange={({ target: { value } }) =>
setter(value === 'all' ? undefined : value)
}
>
<option value="all">all</option>
{options.map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
</label>
);
});
const colors = ['blue', 'red', 'yellow'];
const shapes = ['square', 'circle'];
const App = () => {
const [color, setColor] = React.useState();
const [shape, setShape] = React.useState();
const selectByColor = React.useMemo(
() => createSelectByColor(color),
[color]
);
const selectByShape = React.useMemo(
() => createSelectByShape(shape),
[shape]
);
const byColor = useSelector(selectByColor);
const byShape = useSelector(selectByShape);
return (
<div>
<div>
<SelectList
label="color"
value={color}
setter={setColor}
options={colors}
/>
<SelectList
label="shape"
value={shape}
setter={setShape}
options={shapes}
/>
</div>
<div>
<h4>color</h4>
<List items={byColor} />
<h4>shape</h4>
<List items={byShape} />
</div>
</div>
);
};
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>
<div id="root"></div>