React之redux和react-redux

    技术2023-07-13  95

    1、redux的使用:

    (1)基本概念和 API:

    1.1 Store

    Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。Redux 提供createStore这个函数,用来生成 Store。createStore函数接受另一个函数作为参数,返回新生成的 Store 对象。 import { createStore } from 'redux'; const store = createStore(reducer);

    1.2 State

    state就是store里面存储的数据,store里面可以拥有多个state,Redux规定一个state对应一个View,只要state相同,view就是一样的,反过来也是一样的,可以通过store.getState( )获取。

    import {createStore} from 'redux' const store=createStore(fn); const state=store.getState()

    1.3 Action

    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的唯一的方式

    1.4 store.dispatch( )

    store.dispatch( )是view发出Action的唯一办法。

    store.dispatch({ type:'ADD_TODO', payload:'redux原理' })

    store.dispatch接收一个Action作为参数,将它发送给store通知store来改变state。

    1.5 Reducer

    Store收到Action以后,必须给出一个新的state,这样view才会发生变化。这种state的计算过程就叫做Reducer。 Reducer是一个纯函数,他接收Action和当前state作为参数,返回一个新的state。注意:Reducer必须是一个纯函数,也就是说函数返回的结果必须由参数state和action决定,而且不产生任何副作用也不能修改state和action对象 const reducer =(state,action)=>{ switch(action.type){ case ADD_TODO: return newstate; default return state } }

    (2)redux 案例

    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 counter

    src/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> ) } }

    2、react-redux

    由于上面使用redux时,每次修改state都要重新调用render函数。于是引入了react-redux。

     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 user

    reducers文件夹里新建index.js文件,将两个reducers整个起来。

    import { combineReducers } from "redux" import counter from "./counter" import user from "./user" const rootReducer = combineReducers({ counter, user }) export default rootReducer

    index.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)

     

    Processed: 0.013, SQL: 9