第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > React-Redux应用示例

React-Redux应用示例

时间:2021-05-25 08:19:20

相关推荐

React-Redux应用示例

一、简介

React-Redux 是 Redux 的官方 React 绑定库。React-Redux 能够使React组件从Redux store中读取数据,并且向 store 分发 actions 以更新数据。React-Redux 并不是 Redux 内置,需要单独安装。React-Redux 一般会和 Redux 结合一起使用。

二、安装redux、react-redux

npm install redux

npm install react-redux

三、Provider 和 connect

Provider:它是react-redux 提供的一个 React 组件,作用是把state传给它的所有子组件,也就是说 当你用Provider传入数据后 ,下面的所有子组件都可以共享数据,十分的方便。

Provider的使用方法是:用Provider组件包裹在最外层的组件

<Provider store={ store }>

<App />

</Provider>

注意:一定是在Provider中传store

connect:它是一个高阶组件 所谓高阶组件就是给它传入一个组件,它会返回新的加工后的组件,connect 方法有四个参数([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])后面两个参数可以不写,不写的话它是有默认值的。主要关注前两个参数:mapStateToProps和 mapDispatchToProps;

mapStateToProps如果定义该参数,组件将会监听 Redux store 的变化。任何时候,只要 Redux store 发生改变,mapStateToProps 函数就会被调用。mapDispatchToProps如果传递的是一个对象,那么每个定义在该对象的函数都将被当作 Redux action creator,对象所定义的方法名将作为属性名;每个方法将返回一个新的函数,函数中dispatch方法会将 actioncreator 的返回值作为参数执行。这些属性会被合并到组件的 props 中。

connect的使用方法是:把指定的state和指定的action与React组件连接起来,后面括号里面写UI组件名

connect(mapStateToProps,mapDispatchToProps)(TbItem)

四、示例:

例1:利用react-redux实现计数器

1、目录结构

2、store.js

import {createStore} from "redux";export const ADD = 'ADD';export const MINUS = 'MINUS';function reducer (state= {count:0},action){console.log('Action:',action);switch (action.type) {case ADD:return { count: state.count + 1}case MINUS:return { count: state.count - 1}default:return state}}let store = createStore(reducer);export default store;

3、action.js

function add() {return {type: 'ADD'}}function minus() {return {type: 'MINUS'}}const action = { add,minus }export default action;

4、Counter1.js

import React,{ Component } from "react";import { connect } from "react-redux";import action from "../actions/action";class Counter1 extends Component {render() {return (<div><p>{ this.props.count }</p><button onClick={this.props.add }>Count++</button>&nbsp;&nbsp;&nbsp;<button onClick={ this.props.minus}>count--</button></div>)}}const mapStateToProps = state=> stateconst mapDispatchToProps = {...action}export default connect(mapStateToProps,mapDispatchToProps)(Counter1);

5、App.js

import logo from './logo.svg';import './App.css';import Counter1 from "./components/Counter1";function App() {return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><Counter1 /></header></div>);}export default App;

6、index.js

import React from 'react';import ReactDOM from 'react-dom';import './index.css';import App from './App';import { Provider } from "react-redux";import store from "./store/store";ReactDOM.render(<Provider store={ store }><App /></Provider>,document.getElementById('root'));

action:行为 它是一个对象 里面必有type来指定其类型 这个类型可以理解为你要做什么,reducer要根据action的type来返回不同的state 每个项目有且可以有多个action。它是 store 数据的唯一来源。通过 store.dispatch() 将 action 传到 store。记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。

reducer:可以理解为一个专门处理state的工厂,给它一个旧数据它会根据不同action.type返回新的数据,每个项目有且可以有多个reducer。reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的。

store:store本质上是一个状态树,保存了所有对象的状态。任何UI组件都能直接的从store访问特定对象的状态。每个项目有且只能有一个store。

提供 getState() 方法获取 state;提供 dispatch(action) 方法更新 state;通过 subscribe(listener) 注册监听器;

例2:多组件共享store

(1)constants.js(定义公共方法名

export const ADD_NUMBER = 'ADD_NUMBER'export const SUB_NUMBER = 'SUB_NUMBER'

(2)actionCreators.js(专门存放方法名)

import {ADD_NUMBER,SUB_NUMBER} from "./constants";export const addAction = num => ({type: ADD_NUMBER,num})export const subAction = num => ({type: SUB_NUMBER,num})

(3)reducer.js(存放事件)

import {ADD_NUMBER,SUB_NUMBER} from "../action/constants";const deflateState = {counter: 0}function reducer(state = deflateState,action){switch (action.type){case ADD_NUMBER:return {...state,counter: state.counter + action.num }case SUB_NUMBER:return {...state,counter: state.counter - action.num }default:return state;}}export default reducer;

(4)store.js文件

import { createStore } from "redux";import reducer from "../reducer/reducer";const store = createStore(reducer);export default store;

(5)home.js(Home组件)

import React,{ Component } from "react";import store from "../redux/store/store";import { addAction } from "../redux/action/actionCreators";export default class Home extends Component {constructor(props) {super(props);this.state = {counter: store.getState().counter}}//订阅componentDidMount() {this.unSubscribe = store.subscribe(()=>{this.setState({counter: store.getState().counter})})}//取消订阅componentWillUnmount() {this.unSubscribe();}render() {return (<div><h2>Home</h2><h3>当前: { this.state.counter }</h3><button onClick={ event => this.increment() }>+1</button><button onClick={ event => this.addNumber(5) }>+5</button></div>)}increment(){store.dispatch(addAction(1));}addNumber(num){store.dispatch(addAction(num));}}

(7)about.js(About组件)

import React,{ Component } from "react";import store from "../redux/store/store";import { addAction } from "../redux/action/actionCreators";export default class Home extends Component {constructor(props) {super(props);this.state = {counter: store.getState().counter}}//订阅componentDidMount() {this.unSubscribe = store.subscribe(()=>{this.setState({counter: store.getState().counter})})}//取消订阅componentWillUnmount() {this.unSubscribe();}render() {return (<div><h2>Home</h2><h3>当前: { this.state.counter }</h3><button onClick={ event => this.increment() }>+1</button><button onClick={ event => this.addNumber(5) }>+5</button></div>)}increment(){store.dispatch(addAction(1));}addNumber(num){store.dispatch(addAction(num));}}

(8)App.js

import logo from './logo.svg';import './App.css';import Home from "./components/home";import About from "./components/about";function App() {return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><Home /><About/></header></div>);}export default App;

(9)index.js

import React from 'react';import ReactDOM from 'react-dom';import './index.css';import App from './App';import store from "./redux/store/store";import { Provider } from "react-redux";ReactDOM.render(<Provider store={store}><App /></Provider>,document.getElementById('root'));

例3、合并多个reducer

(1)目录结构

(2)action文件

2.1、changeAge_action.js

export const CLICK_ADD = 'CLICK_ADD';export const CLICK_SUB = 'CLICK_SUB';export function clickAdd() {return {type: CLICK_ADD}}export function clickSub() {return {type: CLICK_SUB}}

2.2、inputInfo.js

export const INPUT_INFO = 'INPUT_INFO';export function inputInfo(name){return {type: INPUT_INFO,name}}

(3)reducer文件

3.1、changeAge_reducer.js

import { CLICK_ADD,CLICK_SUB } from "../actions/changeAge_action";function initialState() {return {age: 20};}function changeAge(state=initialState(),action) {switch (action.type) {case CLICK_ADD: {return {...state,age: state.age + 1}}case CLICK_SUB: {return {...state,age: state.age - 1}}default:return state;}}export default changeAge;

3.2、inputInfo_reducer.js

import { INPUT_INFO } from "../actions/inputInfo_action";function initialState() {return {name: "ZhangSan"}}function inputInfo(state= initialState(),action) {switch (action.type) {case INPUT_INFO: {return {...state,name: action.name}}default:return state;}}export default inputInfo;

3.3、rootReducer.js

(4)store.js文件

import { createStore } from "redux";import rootReducer from "../reducer/rootReducer";const store = createStore(rootReducer);export default store;

(5)组件

5.1、Name组件(name.js)

import React,{ Component } from "react";import PropTypes from "prop-types";import { connect } from "react-redux";class Name extends Component {render() {const { name } = this.propsreturn (<div>My name is <i>{ name }</i></div>)}}Name.propTypes = {name: PropTypes.string.isRequired}const mapStateToProps = (state)=> {return {name: state.Name_store.name}}export default connect(mapStateToProps)(Name);

5.2、Age组件(age.js)

import React,{ Component } from "react";import PropTypes from "prop-types";import { connect } from "react-redux";import {clickAdd,clickSub } from "../actions/changeAge_action";class Age extends Component{constructor(props) {super(props);this.clickAdd = this.clickAdd.bind(this);this.clickSub = this.clickSub.bind(this);}render() {const { age } = this.propsreturn (<div>I am <i>{ age } </i>years old this year&nbsp;&nbsp;&nbsp;<button onClick={this.clickAdd }>Add Age</button><button onClick={this.clickSub }>Sub Age</button></div>)}clickAdd(event) {this.props.dispatch(clickAdd());}clickSub(event) {this.props.dispatch(clickSub());}}Age.propTypes = {age: PropTypes.number.isRequired}const mapStateToProps = (state) => {return {age: state.Age_store.age}}export default connect(mapStateToProps)(Age);

5.3、Form组件(form.js)

import React,{Component} from "react";import {connect} from "react-redux";import { inputInfo } from "../actions/inputInfo_action";class Form extends Component {constructor(props) {super(props);this.clickSubmit = this.clickSubmit.bind(this);}render() {return (<div><input type={"text"} placeholder={"name"} id={"nameInput"}/><button onClick={ this.clickSubmit }>提交</button></div>)}clickSubmit(event) {let name = document.getElementById('nameInput').value;console.log(name);this.props.dispatch(inputInfo(name));}}export default connect()(Form);

(6)App.js

import logo from './logo.svg';import './App.css';import Name from "./redux/components/name";import Age from "./redux/components/age";import Form from "./redux/components/form";function App() {return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><Name /><br/><Age /><br/><Form /></header></div>);}export default App;

(7)index.js

import React from 'react';import ReactDOM from 'react-dom';import './index.css';import App from './App';import { Provider } from "react-redux";import store from "./redux/store/store";ReactDOM.render(<Provider store={ store }><App /></Provider>,document.getElementById('root'));

运行效果:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。