const { Provider, useDispatch, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const { createSelector } = Reselect;
const initialState = {
data: ['aaa', 'aab', 'abb', 'bbb'],
filter: '',
};
//action types
const SET_FILTER = 'SET_FILTER';
//action creators
const setFilter = (filter) => ({
type: SET_FILTER,
payload: filter,
});
const reducer = (state, { type, payload }) => {
if (type === SET_FILTER) {
return {
...state,
filter: payload,
};
}
return state;
};
//selectors
const selectData = (state) => state.data;
const createSelectFilteredData = (filter) =>
createSelector(
[selectData], //re use select data
(data) => data.filter((d) => d.includes(filter))
);
const selectFilter = (state) => state.filter;
//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 Filter = React.memo(function FilterComponent() {
const filter = useSelector(selectFilter);
const dispatch = useDispatch();
return (
<label>
Filter
<input
type="text"
value={filter}
onChange={(e) =>
dispatch(setFilter(e.target.value))
}
/>
</label>
);
});
const FilteredList = React.memo(
function FilteredListComponent() {
const filter = useSelector(selectFilter);
const selectFiltered = React.useMemo(
() => createSelectFilteredData(filter),
[filter]
);
const data = useSelector(selectFiltered);
return (
<ul>
{data.map((d, i) => (
<li key={i}>{d}</li>
))}
</ul>
);
}
);
const App = () => {
return (
<div>
<Filter />
<FilteredList />
</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>