如何在我的代码中使用 React-redux 来避免本地状态?

cod*_*ash 0 reactjs redux react-redux

我正在学习 redux 并且我已经提供了一个使用 store、action 和 reducer 的简单代码。我正在使用 store.subscribe() 来监听状态的变化并用它来更新我的本地状态。

下面是我在 index.js 中的全部代码:

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';

var store = createStore(changeState);
var initialState = {
    qty: 0,
    price: 0
}

function changeState(state = initialState, action) {
    switch (action.type) {
        case 'INCREMENT':
            var stateCopy1 = Object.assign({}, state);
            stateCopy1.qty = stateCopy1.qty + action.qty;
            stateCopy1.price = stateCopy1.price + action.price;
            return stateCopy1;
        default:
            return state;

    }
}

class Home extends React.Component {
    render() {
        return (
            <React.Fragment>
                <Comp1 /><br />
                <Comp2 />
            </React.Fragment>
        )
    }
}
class Comp1 extends React.Component {
    increase = () => {
        var action = {
            type: 'INCREMENT',
            qty: 1,
            price: 100
        }
        store.dispatch(action);
    }


    render() {
        return (
            <button type="button" onClick={this.increase}>Increase</button>
        )
    }

}
class Comp2 extends React.Component {
    constructor() {
        super();
        this.state = {
            cartQty: 0,
            cartPrice: 0
        }
    }
    render() {
        store.subscribe(() => {
            var globalState = store.getState();
            this.setState({cartQty:globalState.qty,cartPrice:globalState.price});
        })
        return (
            <div>
                <h1>Total items in cart: {this.state.cartQty}</h1>
                <h1>Total price of cart :{this.state.cartPrice}</h1>
            </div>
        )
    }
}

ReactDOM.render(<Home />, document.getElementById('root'));
Run Code Online (Sandbox Code Playgroud)

我想使用 react-redux 来避免本地状态和订阅。我阅读了 connect() 和 mapStateToProps() 以及 . 但是我无法弄清楚如何在下面的代码中使用它们。如何在我的代码中实现这些部分?

Mar*_*k E 5

当然可以,首先让我们确保概念清晰。

Redux 已经有一个“状态”,所以你将它复制到你的内部状态是多余的。

connect():
这个方便的方法用于将 redux 的状态映射到组件中的 props。也就是说,您不是将状态复制到另一个状态,而是使用 Redux 的状态作为道具,这些道具是不可变的,更像是对 Redux 内部真实数据的引用。
它是用模式调用hoc构建的,但这是另一个问题的教训。关于 hoc 的重要一点是,它接受一个组件作为参数,并返回一个新组件,一个改进的组件。

mapStateToProps():
这将是您告诉connect您想要进入组件内部的 redux 状态的哪一部分的方式。它是一个方法,它接收完整的 redux 的状态,提取你想要使用的属性,并将它们作为 props 返回给你的组件。

现在你在这里遗漏了 ecuation 的一个关键部分,它是 redux 的...
Provider:
这部分应该包装你的所有应用程序(或者你希望它具有 redux 访问权限的部分,通常是全部)并且是负责将 redux 的 store 发送到树下的人,以便以后connect可以获取它(这是通过 react 的context实现的,但这是另一个日期的一顿饭)。
你得到你的提供者这样的:import {Provider} from 'react-redux';然后你把商店作为道具给它叫做...... store(聪明吗?)

闲话少说,让我们进入正题。

我们从导入开始,让我们得到我们需要的一切:

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import {Provider, connect} from 'react-redux';
Run Code Online (Sandbox Code Playgroud)

我们在这里添加了另外两个东西,Provider组件和connecthoc。

var initialState = {
    qty: 0,
    price: 0
}

function changeState(state = initialState, action) {
    switch (action.type) {
        case 'INCREMENT':
            var stateCopy1 = Object.assign({}, state);
            stateCopy1.qty = stateCopy1.qty + action.qty;
            stateCopy1.price = stateCopy1.price + action.price;
            return stateCopy1;
        default:
            return state;

    }
}
var store = createStore(changeState);
Run Code Online (Sandbox Code Playgroud)

现在,你看到那里发生了什么吗?确切地!没有。您的减速器可以保持原样,我们不会移动它,尽管对于更大的应用程序,您可能想要学习组合减速器

class Home extends React.Component {
    render() {
        return (
            <Provider store={store}>
                <Comp1 /><br />
                <Comp2 />
            </Provider>
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

好的,你Fragment已经走了,我很抱歉,但现在不再需要了。Fragments 用于返回两个或多个组件,但由于Provider正在包装组件,因此无需使用Fragment。
而关于Provider,你只需要把它放在一切之外并给它你的store. 很容易。

class Comp1 extends React.Component {
    increase = () => {
        var action = {
            type: 'INCREMENT',
            qty: 1,
            price: 100
        }
        store.dispatch(action);
    }


    render() {
        return (
            <button type="button" onClick={this.increase}>Increase</button>
        )
    }

}
Run Code Online (Sandbox Code Playgroud)

在最后一个组件中,我们没有移动任何东西。虽然我们应该有,看看你是如何store直接使用你dispatch的action. 在普通应用程序中,此组件将位于另一个文件中,因此您无法访问该store属性。我们的朋友又来了connect,它通过一个叫做mapDispatchToProps你在这里读到的函数帮助我们调度动作,但这也是另一天。

来了,我们都在等待,connect方法:

class Comp2 extends React.Component {

    render() {

        return (
            <div>
                <h1>Total items in cart: {this.props.qty}</h1>
                <h1>Total price of cart :{this.props.price}</h1>
            </div>
        )
    }
}

function mapStateToProps( state ){
    return { qty: state.qty, price:state.price }
}

Comp2 = connect(mapStateToProps)(Comp2);
Run Code Online (Sandbox Code Playgroud)

这可能有点令人困惑,所以让我解释一下:
首先,我们删除了与组件状态相关的所有内容。我们不再使用它了,因为这就是您想要的,对吗?而且组件现在更精简了。而且更凉。
但后来发生了什么?好吧,首先我们要定义mapStateToProps函数。这就是将 redux 的状态转换为你的组件状态。这一次,我们将 redux 状态中的每个属性都发送到您的组件,但在更大的应用程序中情况并非如此,在更大的应用程序中,redux 将拥有内部所有内容的状态,可能是购物车项目,应用程序主题颜色,用户信息等。很多东西,所以在这个函数中,我们只选择我们有兴趣进入我们的组件的属性。
现在 connect 调用...我们正在重新定义我们的组件,这有点奇怪,但我会尝试解释一下。
connect收到我们的mapStateToProps方法,然后是我们的组件。他们在内部交配connect并产生了另一个组件,这个组件将我们首先定义的组件作为子组件,并将始终将我们要求的 redux 状态的部分作为道具发送给它。