react-redux入门
1. Provider
// index.js
import React, { Component, Fragment } from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
import { Provider } from 'react-redux';
import store from "./store.js";
const Main = (
<Provider store={store}>
<App/>
</Provider>
);
ReactDOM.render(Main, document.getElementById('root'));
App
接收的state
数据均来自props
。
// App.js
import React, { Component, Fragment } from "react";
import { connect } from "react-redux";
class App extends Component {
render() {
const { inputValue, list, handleInput, handleButton, handleUlLi } = this.props;
return (
<Fragment>
<input value={inputValue} onChange={handleInput}/>
<button onClick={handleButton}>add</button>
<ul>
{
list.map((item, index) => {
return (
<li key={index} id={index} onClick={handleUlLi}>{item}</li>
)
})
}
</ul>
</Fragment>
)
}
}
const mapStateToProps = (state) => {
return {
inputValue: state.inputValue,
list: state.list
}
};
const mapDispatchToProps = (dispatch) => {
return {
handleInput(e) {
const action = {
type: 'handleInput',
value: e.target.value
};
dispatch(action);
},
handleButton() {
const action = {
type: 'handleButton'
};
dispatch(action);
},
handleUlLi(e) {
const action = {
type: 'handleUlLi',
value: e.target.id
};
dispatch(action);
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
2. 拆分reducer: combineReducers
拆分前的reducer.js
// ./store/reducer.js
let defaultState = {
searchFocus: false,
};
export const reducer = ((state=defaultState, action) => {
if(action.type === 'changeSearchFocus'){
const newState = JSON.parse(JSON.stringify(state));
newState.searchFocus = action.value;
return newState
}
return state
});
拆分后的reducer.js
// ./store/reducer.js
import { combineReducers } from "redux";
import { reducer as reducer_header } from "../header/reducer.js";
export default combineReducers({
header: reducer_header
})
// ./header/reducer.js
let defaultState = {
searchFocus: false,
};
export const reducer = ((state=defaultState, action) => {
if(action.type === 'changeSearchFocus'){
const newState = JSON.parse(JSON.stringify(state));
newState.searchFocus = action.value;
return newState
}
return state
});
3. 新建一个App
以新建一个Home
组件为例。
- App.js
- style.js
- store
|-- store.js
|-- reducer.js
- pages
|-- home // 组件
|-- index.js
|-- style.js
|-- component // 组件拆分
|-- ······
|-- store
|-- index.js
|-- reducer.js
|-- actionCreator.js
|-- actionType.js
|-- detail // 其他组件
|-- ······
笔记–1:调用actionCreator.getEssayList()
会返回一个箭头函数:./pages/home/store/actionCreator.js
,使用redux-thunk
,若dispatch
的参数是一个函数,则dispatch
会调用这个函数,而不会将这个函数发送至reducer
,所以需要在这个函数中(dispatch)=>{}
使用dispatch
方法,向reducer
发送action
。
import { actionCreator } from '../store/index.js';
import { connect } from 'react-redux';
// ······
const mapDispatchToProps = (dispatch) => {
return {
getEssayList() {
dispatch(actionCreator.getEssayList())
}
}
};
export default connect(mapStateToProps, mapDispatchToProps)(Essay)
./store.js
笔记–2:这里使用了redux-devtools
和redux-thunk
。
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import reducer from "./reducer";
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(applyMiddleware(thunk));
const store = createStore(reducer, enhancer);
export default store
./reducer.js
import { combineReducers } from "redux-immutable";
import { reducer as reducer_header } from "../header/store/index.js";
import { reducer as reducer_home } from "../pages/home/store/index.js";
export default combineReducers({
header: reducer_header,
home: reducer_home,
})
./pages/home/store/index.js
笔记–3:将所有的action
和type
,以及reducer
打包到index.js
中,react会自动搜索引用路径下的index.js
文件。
import * as actionCreator from './actionCreator.js';
import * as actionType from './actionType.js';
import { reducer } from "./reducer.js";
export { actionCreator, actionType, reducer }
./pages/home/store/reducer.js
import * as actionType from './actionType.js';
import { fromJS } from 'immutable';
let defaultState = fromJS({
essay: []
});
export const reducer = ((state=defaultState, action) => {
switch(action.type){
case actionType.ChangeEssayList:
return state.set('essay', action.value);
default:
return state
}
});
./pages/home/store/actionType.js
export const ChangeEssayList = 'changeEssayList';
./pages/home/store/actionCreator.js
import * as actionType from './actionType.js';
import axios from 'axios';
import { fromJS } from "immutable";
const changeEssayList = (value) => ({
type: actionType.ChangeEssayList,
value: value
});
export const getEssayList = (value) => {
return (dispatch) => {
axios.get('/api/essay.json')
.then((res)=>{
dispatch(changeEssayList(fromJS(res.data.data)))
})
}
};