react中如何使用redux(react-redux)
首先声明:redux仅仅作为数据层框架,与react没有直接的联系,他可以应用与angular等其他视图层框架,或者直接导入使用
redux核心分为三部分:
store: redux的核心,暴露一些方法:getState() dispatch() subscrible(),store在整个应用中是唯一的,并且不能直接被修改,必须通过reduce修改
reduce:指定了应用状态的变化如何响应 actions 并发送到 store 的
action:一个纯JS对象,用来告诉reduce应该如何改变state,多数情况下,会有一个 type 值,且会被定义成字符串常量
实例:
index.js
import { createStore } from 'redux' import reduce from './reduce' const store = createStore(reduce, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()) export default store
第二个参数
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
是给Redux开发者工具使用,添加后浏览器图标会激活
reduce.js
const defaultState = { data: [ 'Racing car sprays burning fuel into crowd.', 'Japanese princess to wed commoner.', 'Australian walks 100km after outback crash.', 'Man charged over missing wedding girl.', 'Los Angeles battles huge wildfires.' ] } export default function reducer(state = defaultState, action){ switch (action.type) { case 'ADD_RECORD': return Object.assign( {}, state, { data: [...state.data, action.text] } ) case 'DEL_RECORD': var data = [...state.data] data.splice(action.index, 1) return Object.assign( {}, state, { data } ) default: return state } }
每当调用store的dispatch方法,会执行reduce函数,reduce要求我们返回一个state,reduce中有以下注意点:
- 不能直接修改state
- 不能执行有副作用的操作,如 API 请求和路由跳转
- 不能调用非纯函数,如
Date.now()
或Math.random()
- 大多数情况下,state的数据格式我们可以在初始化的时候可以确定,因此我们可以定义一个默认的
action
export const addRecord = function(text){ return { type: 'ADD_RECORD', text } } export const delRecord = function(index){ return { type: 'DEL_RECORD', index } }
在需要修改store状态的组件中触发reduce修改state
import store from './store' import { addRecord } from './store/action' class Mycomponent extends Component { ... addRecord(){ //调用 dispatch ,参数为一个 action store.dispatch( addRecord(this.state.inputVal) ) } ... }
在调用store组件订阅store,实时响应
import store from './store' class MyList extends React.Component{ constructor(props){ super(props) this.state = { ...store.getState() } store.subscribe(() => { this.setState({ ...store.getState() }) }) } ... }
reacte-redux
以上这种动手订阅的方式十分繁琐,因此推荐使用专为react打造的第三库 react-redux 去连接redux
使用:
npm install react-redux --save
在index.js文件中引入 Provider 组件,将它包在最外层,把 store 作为 prop 传入 Provider
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.jsx'; import { Provider } from 'react-redux' import store from './store' const Application = ( <Provider store={store}> <App /> </Provider> ) ReactDOM.render(Application, document.getElementById('root'));
在应用组件中通过 connect 将组件与 store 关联起来,然后可以通过直接访问 props 的方式访问 store
import React from 'react' import { connect } from 'react-redux' import { delRecord } from './store/action' class MyList extends React.Component{ render(){ return ( <ul className="list-container"> {this.props.data.map((item, index) => ( <li key={index} onClick={() => { this.props.delRecord(index) }}>{item}</li> ))} </ul> ) } } const mapStateToProps = (state) => ({ ...state }) const mapDispatchToProps = (dispatch) => ({ delRecord(index){ dispatch(delRecord(index)) } }) export default connect(mapStateToProps, mapDispatchToProps)(MyList)
其中 connect 是一个高阶函数
第一个参数