react-redux使用入门
什么是redux?
redux是项目的状态管理库,对于大的项目尤其有用,和react本身并不相关,可以和任何框架融合。对于一个项目而言,主要的数据可能是这样的:
state = {
todos: [{
text: 'Eat food',
completed: true
}, {
text: 'Exercise',
completed: false
}],
visibilityFilter: 'SHOW_COMPLETED'
}
这样的数据在各个组件之间共享,想要改变state中的值,要通过一种触发action的方式实现,一个action就是这样的一个对象:
{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
而reducer就是接收这样的action,然后返回新的state值的函数,像下面这样:
function visibilityFilter(state = 'SHOW_ALL', action) {
if (action.type === 'SET_VISIBILITY_FILTER') {
return action.filter;
} else {
return state;
}
}
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([{ text: action.text, completed: false }]);
case 'TOGGLE_TODO':
return state.map((todo, index) =>
action.index === index ?
{ text: todo.text, completed: !todo.completed } :
todo
)
default:
return state;
}
}
这就是redux的基本思想。
至于redux的基本API,这里不做介绍。
下面大家可以跟着我一步一步来在一个react项目中使用redux,加粗部分才是需要的代码哦。
首先需要安装redux和react-redux
npm install redux
npm install react-redux
建立redux.js文件
然后,我们可以先设计一下项目的state
// redux.js
const initialState = {
searchHistory: ['大码女鞋','男装保暖加厚','冰箱三开门']
}
日后我们要定义的action可能是长这样的:
{
type: ADD_TO_SEARCH_HISTORY,
payload: '男装'
}
编写一个reducer来处理这个searchHistory:
// redux.js
const handleSearchHistory = (state = initialState, action) => {
console.log(action);
switch (action.type) {
case ADD_TO_SEARCH_HISTORY:
return
{...state, searchHistory:state.searchHistory.concat([action.payload])};
default:
return state;
}
}
下面,调用redux的combineReducers
// redux.js
let rootReducers = combineReducers({
handleSearchHistory: handleSearchHistory
})
再利用redux的createStore来创立一个store
// redux.js
let store = createStore(rootReducers);
export default store;
到这里我们都还没有用到react-redux,下面开始使用
建立search.js文件,在其中编写一个简单的SearchComponent组件
// search.js
class SearchComponent extends React.Component {
constructor() {
super();
this.state = {
searchHistory: []
}
}
render() {
return (
<div>
{this.state.searchHistory.map((item, index) => <div key={index}>{item}</div>)}
</div>
)
}
}
export default SearchComponent;
如何将SearchComponent和store建立联系呢?
在项目的根节点文件中像这样把store传递给所有的组件:
Provider是react-redux的api,可以把store传递给所有的组件。
import { Provider } from 'react-redux'
ReactDOM.render(
<Provider store={store}>
<App />,
</Provider>
document.getElementById('root')
);
回到search.js,先把下面的代码写入,我们后面再解释:
// search.js
const mapStateToProps = (state) => {
return {
state: state
}
}
const Search = connect(mapStateToProps)(SearchComponent);
export default Search;
connect是react-redux的api,是这样的形式
connect(mapStateToProps, mapDispatchToProps)(SearchComponent)
其中,mapStateToProps用来把项目的state传给props,mapDispatchToProps可以把dispatch传给props,我们暂时可以不用这个参数,只用前一个参数。
之后,可以在 search.js 中访问到项目的state,以下面的方式来访问
this.props.state.handleSearchHistory
注意这里的handleSearchHistory是上面我们编写reducer的时候,命名的属性值哦。
let rootReducers = combineReducers({
handleSearchHistory: handleSearchHistory
})
然后我们来修改 search.js
// search.js
class SearchComponent extends React.Component {
constructor() {
super();
}
render() {
return (
<div>
{this.props.state.handleSearchHistory.searchHistory
.map((item, index) => <div key={index}>{item}</div>)}
</div>
)
}
}
const mapStateToProps = (state) => {
return {
state: state
}
}
const Search = connect(mapStateToProps)(SearchComponent);
export default Search;
此时的 redux.js 文件应该是这样的:
// redux.js
import { combineReducers, createStore } from 'redux';
const initialState = {
searchHistory: ['大码女鞋','男装保暖加厚','冰箱三开门']
}
// action.payload是一个字符串
const handleSearchHistory = (state = initialState, action) => {
console.log(action);
switch (action.type) {
case ADD_TO_SEARCH_HISTORY:
return
{...state, searchHistory:state.searchHistory.concat([action.payload])};
default:
return state;
}
}
let rootReducers = combineReducers({
handleSearchHistory: handleSearchHistory
})
let store = createStore(rootReducers);
export default store;
到这里,已经实现了在SearchComponent中访问项目state,下面我们再来看看如何在SearchComponent中来触发一个dispatch.
修改 search.js
render() {
return (
<div>
{this.props.state.handleSearchHistory.searchHistory
.map((item, index) => <div key={index}>{item}</div>)}
<button onClick={() => this.props.dispatch({
type: ADD_TO_SEARCH_HISTORY,
payload: '男装'
})}></button>
</div>
)
}
这样显示地触发了dispatch,还记得上面提到的connect接收的另一个参数mapDispatchToProps吗?这个时候就用上了,我们来看看。
继续完善 search.js,添加如下代码:
const addSearchHistory = (value) => {
return {
type: ADD_TO_SEARCH_HISTORY,
payload: value
}
}
const mapDispatchToProps = (dispatch) => {
return {
addSearchHistory: (currentValue) => dispatch(addSearchHistory(currentValue)),
deleteSearchHistory: () => dispatch(deleteSearchHistory())
}
}
const Search = connect(mapStateToProps, mapDispatchToProps)(SearchComponent);
export default Search;
之后,我们就可以在 search.js 中像这样触发dispatch
this.props.addSearchHistory('男装');
此时,完整的 search.js 代码如下:
// search.js
class SearchComponent extends React.Component {
constructor() {
super();
}
render() {
return (
<div>
{this.props.state.handleSearchHistory.searchHistory
.map((item, index) => <div key={index}>{item}</div>)}
<button onClick={() => this.props.addSearchHistory('男装')}></button>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
state: state
}
}
const addSearchHistory = (value) => {
return {
type: ADD_TO_SEARCH_HISTORY,
payload: value
}
}
const mapDispatchToProps = (dispatch) => {
return {
addSearchHistory: (currentValue) => dispatch(addSearchHistory(currentValue)),
deleteSearchHistory: () => dispatch(deleteSearchHistory())
}
}
const Search = connect(mapStateToProps, mapDispatchToProps)(SearchComponent)
export default Search;
我们现在只管理了项目中 state 中的 searchHistory一项数据,如果有多项数据要管理的话,就要编写多个reducer,写在一个文件里就会臃肿,可以分开到多个文件中;像 search.js 中的 addSearchHistory 方法也可以写到单独的文件中去。不过,这和技术就无关了,只是项目的优化。
本文详细介绍如何在React项目中集成Redux状态管理库,包括安装、配置、创建reducer、连接组件和触发dispatch等步骤。

555

被折叠的 条评论
为什么被折叠?



