React: Redux案例一

大家好,我是梅巴哥er。上篇介绍了redux , react-redux以及redux调试工具的使用,那么本篇就写一个redux案例,加深对redux的理解。另外,因为这个案例过于简单,只用到一个reducer,所以本篇就没有用到combineReducers

老规矩,写代码前,先来看下渲染效果图:
在这里插入图片描述
(还好这里点击按钮会有个动效,能看到我点击了哪个按钮😂)
左边是渲染结果,右边是redux调试工具的显示内容。

案例功能说明:

  • 左边是select选择框,右边依次是 + - 和异步增加的按钮
  • 选择select,点击按钮依次渲染不同的效果
  • 点击的次数times在0和1次时,显示time,2次以上时,显示times复数形式。
  • 当点击-号时,如果time会变成负数,那就不更新状态,同时提示“次数不能为负数”

项目结构:
在这里插入图片描述

代码:(注:以下代码均写在src文件夹里)
1,入口文件index.js

import React from 'react'
import ReactDOM from 'react-dom'
// import App1 from './components/App1'
import App3 from './containers/App3' // 这里改成了从容器组件中引入带有connect的app3
import store from './redux/store'
import {Provider} from 'react-redux'


//监听
// function render() {
//     ReactDOM.render(
//         <App2 store={store} />, // 把store传给子组件
//         document.getElementById('root')
//     )
// }
// render()
// store.subscribe(render)

// 有了Provider,就不需要做监听了
// 把要渲染的根组件放在Provider组件里,然后store交给Provider就可以了
ReactDOM.render(
    <Provider store={store}>
        <App3 />  {/* 根组件也改成了app3 */}
    </Provider>,
    // <App2 store={store} />, // 把store传给子组件
    document.getElementById('root')
)

2,UI组件App2.js

import React, { Component } from 'react'
import PropTypes from 'prop-types'


export default class App2 extends Component {
    // 改用react-redux后,要先声明需要接收的属性
    static propTypes = {
        count: PropTypes.number.isRequired,
        incrementAction: PropTypes.func.isRequired,
        decrementAction: PropTypes.func.isRequired,
        delayAddAction: PropTypes.func.isRequired
    }
    
    increment = () => {
        // 1,获取选择框里的值
        const number = this.select.value*1 // *1是为了把字符串转换成数字类型
        // 调用store的方法更新状态
        // this.props.store.dispatch(incrementAction(number))
        // react-redux 这里改成:
        this.props.incrementAction(number)
    }
    decrement = () => {
        // 1,获取选择框里的值
        const number = this.select.value*1 // *1是为了把字符串转换成数字类型
        // 调用store的方法更新状态
        // this.props.store.dispatch(decrementAction(number))
        // react-redux 这里改成:
        this.props.decrementAction(number)
    }
    delayAdd = () => { // 异步延时增加
        const number = this.select.value*1
        this.props.delayAddAction(number)
    }
    render() {
        // const count = this.props.store.getState() 
        // react-redux 这里也要改一下:
        const {count} = this.props
        return (
            <div>
                <p>click { count } time{ count >= 2 ? <span>s</span> : null } </p>
                <div>
                    <select ref={select => this.select = select} >
                        <option value="1">1</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                    </select>&nbsp;
                    <button onClick={ this.increment } >+</button>&nbsp;
                    <button onClick={ this.decrement }>-</button>&nbsp;
                    <button onClick={this.delayAdd} >异步延时增加</button>
                </div>
            </div>
        )
    }
}


3,容器组件App3.js

// import React, { Component } from 'react'
import {incrementAction, decrementAction, delayAddAction} from '../redux/actions'
import {connect} from 'react-redux'
import App2 from '../components/App2'


// connect连接组件和redux
export default connect(
    state => ({count: state}), // 这里的state是reducer管理的state
    {incrementAction, decrementAction, delayAddAction} // 这俩是action函数。这里最好和声明接收的参数保持一致,就更简洁了。
)(App2) //App2是连接的组件

4,action类型(事件名称)action-types.js

// 所有的action的类型(type)都写在这里,方便识别和查找,以免重复

// 增加值
export const INCREMENT = 'increment'

// 减少值
export const DECREMENT = 'decrement'

5,action对象,因为action的数据是以参数的形式传递过来的,所以这里写成函数返回的action对象。
action.js

import { number } from "prop-types"
// 包含所有的action对象

import { INCREMENT, DECREMENT } from "./action-types"

// 增加的action
export const incrementAction = (number) => ({
    type: INCREMENT,
    data: number
})
// 减少的action
export const decrementAction = (number) => ({
    type: DECREMENT,
    data: number
})
// 异步延时增加
export const delayAddAction = (number) => {
    return dispatch => {
        setTimeout(() => {
            // 所有的异步action  都有同步action去分事件
            dispatch(incrementAction(number))
        }, 1000);
    }
}

6,仓库store.js(仓库是唯一的,不用加s)

import {createStore, applyMiddleware} from 'redux'
import {counter} from './reducers'
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'

// 生成一个store对象,连接管理员counter
const store = createStore(
	counter,
	composeWithDevTools(applyMiddleware(thunk))
)
// console.log(store)

export default store 

7,仓库管理员reducers.js

// 包含多个reducer函数的文件
import {INCREMENT, DECREMENT} from './action-types'

export function counter(state = 0, action) {
    switch(action.type) {
        case INCREMENT:
            return state + action.data
        case DECREMENT:
            if (state - action.data >= 0) {
                return state - action.data
            } else {
                alert('次数不能为负!')
                return state
            }
            // break
        default:
            return state
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值