state就是store里面存储的数据,store里面可以拥有多个state,Redux规定一个state对应一个View,只要state相同,view就是一样的,反过来也是一样的,可以通过store.getState( )获取。
import {createStore} from 'redux' const store=createStore(fn); const state=store.getState()state的改变会导致View的变化,但是在redux中不能直接操作state也就是说不能使用this.setState来操作,用户只能接触到View。在Redux中提供了一个对象来告诉Store需要改变state。Action是一个对象其中type属性是必须的,表示Action的名称,其他的可以根据需求自由设置。
const action={ type:'ADD_TODO', payload:'redux原理' }在上面代码中,Action的名称是ADD_TODO,携带的数据是字符串‘redux原理’,Action描述当前发生的事情,这是改变state的唯一的方式
store.dispatch( )是view发出Action的唯一办法。
store.dispatch({ type:'ADD_TODO', payload:'redux原理' })store.dispatch接收一个Action作为参数,将它发送给store通知store来改变state。
src/index.js代码:
/** * src/index.js */ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import {createStore} from 'redux' import reducer from './reducers/counter' // 创建仓库,参数是reducer const store = createStore(reducer) const renderDom = () => { ReactDOM.render( <React.StrictMode> {/* 父组件传值给子组件,value就是获取状态中的值,onIncrement和onDecrement是一个执行dispatch的函数 */} <App value = {store.getState()} onIncrement={() => {store.dispatch({type: "INCREMENT"})}} onDecrement={() => {store.dispatch({type: "DECREMENT"})}} /> </React.StrictMode>, document.getElementById('root') ); } renderDom(); // 监听数据变化,只要state变化,就会重新执行renderDom函数 store.subscribe(renderDom)src/reducers/counter.js 代码
/** * src/reducers/counter.js */ import * as constants from './../constants' const counter = (state=0, action) => { switch(action.type) { case constants.INCREMENT: return state+1; case constants.DECREMENT: return state-1 default: return state; } } export default countersrc/App.js 代码
/** * src/App.js */ import React from 'react'; export default class App extends React.Component{ render() { console.log (this.props) let {value, onIncrement, onDecrement} = this.props return ( <div className="App"> <p>{value}</p> <button onClick={onIncrement}>加1</button> <button onClick={onDecrement}>减1</button> </div> ) } }src/index.js 代码
/** * src/index.js */ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import {createStore} from 'redux' import reducer from './reducers/counter' // 引入react-redux中的Provider,是一个组件,只要包含在这个组件内的页面都可以使用store import { Provider } from "react-redux" // 创建仓库,参数是reducer const store = createStore(reducer) ReactDOM.render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode>, document.getElementById('root') );src/App.js 代码
/** * src/App.js */ import React from 'react'; import {connect} from 'react-redux' import {increment, decrement} from './actions/counter' class App extends React.Component{ render() { console.log (this.props) let {counter, increment, decrement} = this.props return ( <div className="App"> <p>{counter}</p> <button onClick={()=>increment(5)}>加</button> <button onClick={()=>decrement(10)}>减</button> </div> ) } } const mapStateToProps = (state) => { return { counter:state } } const mapDispatchToProps = (dispatch) => { return { increment: (num) => {dispatch(increment(num))}, decrement: (num) => {dispatch(decrement(num))} } } export default connect(mapStateToProps, mapDispatchToProps)(App)其中,新增了actions/counter.js文件
import * as constants from './../constants' export function increment (num) { console.log(num) return { type: constants.INCREMENT, num } } export function decrement (num) { return { type: constants.DECREMENT, num } }如果 actions/counter.js 中很多方法,调用起来就很复杂,可以整合一下。
src/App.js 代码
/** * src/App.js */ import React from 'react'; import {connect} from 'react-redux' // import {increment, decrement} from './actions/counter' import * as counterActions from './actions/counter' import {bindActionCreators} from 'redux' class App extends React.Component{ render() { console.log (this.props) let {counter, counterActions} = this.props return ( <div className="App"> <p>{counter}</p> <button onClick={()=>counterActions.increment(5)}>加</button> <button onClick={()=>counterActions.decrement(10)}>减</button> </div> ) } } const mapStateToProps = (state) => { return { counter:state } } const mapDispatchToProps = (dispatch) => { return { counterActions: bindActionCreators(counterActions, dispatch) } } export default connect(mapStateToProps, mapDispatchToProps)(App)
现在是只有一个counter模块,如果又有user模块的数据,那就要使用到combineReducers了
reducers文件夹里新建user.js文件,创建一个user的reducers
import { FETCH_USER_SUCCESS } from "../constants" const initialState = { user:{} } const user = ( state = initialState,action ) => { switch(action.type){ case FETCH_USER_SUCCESS: return { user: action.user }; default: return state; } } export default userreducers文件夹里新建index.js文件,将两个reducers整个起来。
import { combineReducers } from "redux" import counter from "./counter" import user from "./user" const rootReducer = combineReducers({ counter, user }) export default rootReducerindex.js引入
import rootReducer from "./reducers" const store = createStore(rootReducer)在actions文件夹里新建user.js
import { FETCH_USER_SUCCESS } from "../constants" export const get_user = (user) => { return { type: FETCH_USER_SUCCESS, user } };新建user页面
import React from 'react' import {connect} from 'react-redux' import {bindActionCreators} from 'redux' import * as userActions from './../actions/user' class User extends React.Component{ render () { let {user, userActions} = this.props console.log(user, userActions) return( <div> { Object.keys(user.user).length === 0 ? <p>User</p> : <p>{user.user}</p> } <button onClick={ () => { userActions.get_user('gfz') } }>getUser</button> </div> ) } } const mapStateToProps = (state) => { return { user: state.user } } const mapDispatchToProps = (dispatch) => { return { userActions: bindActionCreators(userActions,dispatch) } } export default connect(mapStateToProps, mapDispatchToProps)(User)