最近在学习redux,关于action,store,reducer感觉理解起来并不困难。。。
但是结合react,使用react-redux中的一些API进行组件的props与aciton和store的连接时就各种不理解了。。。
首先react-redux中有容器组件和展示组件这两个概念。
我的展示组件如下:component/app.js
class AppComponent extends React.Component {
render() {
const { value, increment, decrement } = this.props;
return (
<div>
{value}<button onClick={increment}>加</button>
<button onClick={decrement}>减</button>
</div>
);
}
}
AppComponent.propTypes = {
value: PropTypes.number.isRequired,
increment: PropTypes.func.isRequired,
decrement: PropTypes.func.isRequired
};
export default AppComponent;
就是一个数字,加,减。
然后我的 reducer/counter.js
import {INCREMENT, DECREMENT} from '../actions/const';
const initialState = {
number: 0
};
function reducer(state = initialState, action) {
switch (action.type) {
case INCREMENT: {
return state.number + 1;
}
case DECREMENT: {
return state.number - 1;
}
default: {
return state;
}
}
}
module.exports = reducer;
我的初始state是{number:0}
最后是关键的container,也就是容器组件:container/app.js
import React, { Component, PropTypes } from 'react';
import { increment, decrement } from '../actions/';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Main from '../components/App';
class App extends Component {
render() {
const {actions, counter} = this.props;
return <Main actions={actions} counter={counter}/>;
}
}
App.propTypes = {
actions: PropTypes.object.isRequired,
counter: PropTypes.object.isRequired
};
function mapStateToProps(state) {
const props = { value: state.counter.number };
return props;
}
function mapDispatchToProps(dispatch) {
const actions = {increment,decrement};
const actionMap = { actions: bindActionCreators(actions, dispatch) };
return actionMap;
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
这里有几个问题:
1:首先,报错:展示组件内的props均报错
Failed prop type: Required prop (value,increment,decrement这三个props) was not specified in AppComponent
.(说明我的3个props没有与action和store内的state联系?)
2:我是按照官方的todoMVC的代码写的容器组件。其中为什么要单独加一个 Class app?
其中return <Main actions={actions} counter={counter}/>的action和counter如何理解?是从哪里传过来的?
3: mapStateToProps中state.counter的counter是哪里来的?(我看的许多例子。。这个state.后面跟的貌似都是reducer的文件名。) 然后,我的value为什么没有取到reducer内的number:0 呢?
4:最后,mapDispatchToProps函数内,并没有显示的看到我组件内的increment和我的action:increment(decrement同理) 建立联系,那么action和props是如何连接的呢?
报错和这些问题纠结了很久了。。因为要问的话,要贴太多代码了。一直找不到好的方式问。。。最后还是以这样凌乱的方式。。真的非常抱歉
还请大神们赐教。。非常非常感谢Orz。
我是题主。刚终于解决了自己的问题。。
现在写下问题的答案,以及一些总结。其实我的问题很简单。。。就是传值的写法问题。自己没有弄懂。就瞎问。耽误了许多大神们时间。
1:第一个问题。为什么会报错。是因为我根本没有将组建内的三个props传递下来。
其中的actions和counter是从store中传递过来的actions和counter。
这里需要这样写:
需要将组建内的props传递下来,并传递state和action给他们。我们在这里就显示的建立了连接了!
2:为什么要加一个Class app?actuions和counter哪里来的?
我做的这个例子只有一个组件。所以其实不需要这样写。
但是如果,container内需要添加多个组件的时候,我们就需要将组件集中起来,将所有的组件合并。
至于,actions和counter哪里来的。上面也提到了。是通过connect传递过来的!
mapStateToProps和mapDispatchToProps一个把store中的state传递了过来,一个把绑定好的actions传递了过来
3,4:上面其实也已经提到了。
它将store内counter这个reducer内的state传递给了counter,再传递给了我们的组件。
它将所有的actions绑定到了store上,然后组件可以通过actions.<name of actions>传递action给我们的组件
最后。这几处改完后,我发现我的reducer也写错了。。我的state是一个对象,必须返回一个新的对象。否则reducer就不是纯函数了~