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{' '}
<input
type="radio"
name="filter"
onChange={() => filterSelected('ALL')}
/>
important{' '}
<input
type="radio"
name="filter"
onChange={() => filterSelected('IMPORTANT')}
/>
nonimportant{' '}
<input
type="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.filter
default:
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{' '}
<input
type="radio"
name="filter"
onChange={() => dispatch(filterChange('ALL'))}
/>
important{' '}
<input
type="radio"
name="filter"
onChange={() => dispatch(filterChange('IMPORTANT'))}
/>
nonimportant{' '}
<input
type="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的变化