复习练手用。先回顾一下redux是怎么工作的:
无状态组件负责渲染以及用户交互(比如点击),它只有props。store的state通过容器组件注入到无状态组件,引起重新渲染,容器组件可以派发action,引起store的state改变。容器组件通过connect函数创建,connect是一个柯里化函数,第一、二个参数分别指定state如何被映射到无状态组件的props,以及要派发的动作如何映射到无状态组件的props(这种props通常是函数,比如onClick之类的)。
项目层次如下:
1、我的习惯是先写Action,下面是Action.js:
export const INCREASE='INCREASE';
export const DECREASE='DECREASE';
export function incActionGenerator(){
return {
type:INCREASE,
preload:'increase the current value'
}
}
export function decActionGenerator(){
return {
type:DECREASE,
preload:'decrease the current value'
}
}
2、然后写Reducer.js:
import {
INCREASE, DECREASE
} from "../actions/Action";
const changeValue=(state={value:0},action)=>{
switch(action.type){
case INCREASE:
return {...state,value:state.value+1};
//return {value:state.value+1};//这样写也ok
case DECREASE:
return {...state,value:state.value-1};
default:
return state;
}
}
export default changeValue;
3、再然后写无状态组件Counter.js:
import React from 'react';
import PropTypes from 'prop-types'
const Counter=({value,onIncClick,onDecClick})=>{
return (
<div>
<span >{value}</span>
<br />
<button type="button" onClick={onIncClick}>Increase</button>
<button type="button" onClick={onDecClick}>Decrease</button>
</div>
)
};
Counter.propTypes = {
value: PropTypes.number.isRequired,
onIncClick: PropTypes.func.isRequired,
onDecClick: PropTypes.func.isRequired
};
我写的还是比较优雅的(^_^),无状态组件写成一个纯函数,而不是写成类:
//class风格的组件,不推荐
class Counter extends React.Component {
render() {
const {value,onIncClick,onDecClick}=this.props;
return (
<div>
<span >{value}</span>
<br />
<button type="button" onClick={onIncClick}>Increase</button>
<button type="button" onClick={onDecClick}>Decrease</button>
</div>
)
}
}
4、然后用写容器组件(CounterContainer.js),对无状态组件进行包裹,注意React的组件首字母一定要大写:
import {connect} from 'react-redux'
import Counter from '../components/Counter'
import {incActionGenerator,decActionGenerator} from "../actions/Action";
const mapStateToProps=(state)=>({
value:state.value
})
const mapDispatchToProps=(dispatch)=>({
onIncClick:()=>dispatch(incActionGenerator()),
onDecClick:()=>dispatch(decActionGenerator())
})
const MyCounterApp=connect(
mapStateToProps,
mapDispatchToProps
)(Counter);
export default MyCounterApp;
5、最后在应用入口(index.js)创建全局的store:
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import changeValue from './reducers/Reducer'
import MyCounterApp from "./containers/CounterContainer";
const store = createStore(changeValue);//用reducer来创建store
ReactDOM.render(
<Provider store={store}>
<MyCounterApp/>
</Provider>,
document.getElementById('root')
);
这样就写完啦!