react-redux使用入门

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,加粗部分才是需要的代码哦。
首先需要安装reduxreact-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;
	}
}
下面,调用reduxcombineReducers
// redux.js
let rootReducers = combineReducers({
	handleSearchHistory: handleSearchHistory
})
再利用reduxcreateStore来创立一个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;

如何将SearchComponentstore建立联系呢?

在项目的根节点文件中像这样把store传递给所有的组件:

Providerreact-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;

connectreact-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 方法也可以写到单独的文件中去。不过,这和技术就无关了,只是项目的优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值