Store with complex state
添加radio实现过滤功能
import React from 'react'import Notes from './components/Notes'import NewNote from './components/NewNote'const App = () => {const filterSelected = (value) => {console.log(value)}return (<div><NewNote /><div>all{' '}<inputtype="radio"name="filter"onChange={() => filterSelected('ALL')}/>important{' '}<inputtype="radio"name="filter"onChange={() => filterSelected('IMPORTANT')}/>nonimportant{' '}<inputtype="radio"name="filter"onChange={() => filterSelected('NONIMPORTANT')}/></div><Notes /></div>)}export default App
input组件type为radio, 都有相同的name, 形成一个单选按钮组
Combined reducers
单选按钮组的状态也应该存储在store中
即使用store.getState()应得到下面的值
{notes: [{ content: 'reducer defines how redux store works', important: true, id: 1},{ content: 'state of store can contain any data', important: false, id: 2}],filter: 'IMPORTANT'}
为filter创建单独的reducer
const filterReducer = (state = 'ALL', action) => {switch (action.type) {case 'SET_FILTER':return action.filterdefault:return state}}export const filterChange = (filter) => {return {type: 'SET_FILTER',filter,}}export default filterReducer
将filterReducer和noteReducer组合成新的reducer
import React from 'react'import ReactDOM from 'react-dom'import { createStore, combineReducers } from 'redux'import noteReducer from './reducers/noteReducer'import filterReducer from './reducers/filterReducer'import { filterChange } from './reducers/filterReducer'import { createNote } from './reducers/noteReducer'const reducer = combineReducers({notes: noteReducer,filter: filterReducer,})const store = createStore(reducer)console.log(store.getState())const renderApp = () => {ReactDOM.render(// <Provider store={store}>// <App />// </Provider>,<div />,document.getElementById('root'))}renderApp()// store.subscribe(renderApp)store.subscribe(() => console.log(store.getState()))store.dispatch(filterChange('IMPORTANT'))store.dispatch(createNote('combineReducers forms one reducer from many simple reducers'))
通过combineReducers将多个reducer组合成一个复合reducer
组合reducer的工作方式使得每个action 在组合reducer的每个部分都得到处理。 通常只有一个reducer对任何给定的action感兴趣,但是在有些情况下,多个reducer根据相同的action改变它们各自的状态部分。
Finishing the filters
将filter分离到单独的组件
import React from 'react'import { filterChange } from '../reducers/filterReducer'import { useDispatch } from 'react-redux'const VisibilityFilter = () => {const dispatch = useDispatch()return (<div>all{' '}<inputtype="radio"name="filter"onChange={() => dispatch(filterChange('ALL'))}/>important{' '}<inputtype="radio"name="filter"onChange={() => dispatch(filterChange('IMPORTANT'))}/>nonimportant{' '}<inputtype="radio"name="filter"onChange={() => dispatch(filterChange('NONIMPORTANT'))}/></div>)}export default VisibilityFilter
通过修改Notes组件的useSelector实现过滤功能
const Notes = () => {const dispatch = useDispatch()const notes = useSelector((state) => {if (state.filter === 'ALL') {return state.notes}return state.filter === 'IMPORTANT'? state.notes.filter((note) => note.important): state.notes.filter((note) => !note.important)})// ...}
Redux DevTools
可以安装Redux DevToolsChrome插件, 用于监视redux-store的状态和改变它的action
在调试时,还有软件库redux-devtools-extension
安装
npm install --save-dev redux-devtools-extension
createStore时使用composeWithDevTools()
import React from 'react'import ReactDOM from 'react-dom'import { createStore, combineReducers } from 'redux'import { Provider } from 'react-redux'import noteReducer from './reducers/noteReducer'import filterReducer from './reducers/filterReducer'import App from './App'import { composeWithDevTools } from 'redux-devtools-extension'const reducer = combineReducers({notes: noteReducer,filter: filterReducer,})const store = createStore(reducer, composeWithDevTools())const renderApp = () => {ReactDOM.render(<Provider store={store}><App /></Provider>,document.getElementById('root'))}renderApp()
重新启动应用,此时在控制台会看到Redux标签,可以清楚地看到store和action的变化
