简体   繁体   English

如何在多个组件中共享redux store

[英]How to share redux store in multiple components

Hi I have one component in which I integrated the redux in my react application. 嗨,我有一个组件,我在我的反应应用程序中集成了redux。 I am opening second then third component. 我打开第二个然后是第三个组件。 I don't want the pass the data which I obtained in first component to second then third in props. 我不希望将我在第一个组件中获得的数据传递给道具中的第二个然后第三个。

I want to do this using redux store. 我想使用redux store来做到这一点。 Is there any way to do this ? 有没有办法做到这一点?

App.js App.js

import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
import RoundedButton from "./RoundedButton";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import * as actions from "./actions/index";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      score: 0,
      status: "",
      userSelected: "",
      computerSelected: "",
      visibility: [true, true, true],
      buttonVisibility: false
    };
    this.clickitem = this.clickitem.bind(this);
    this.handlePlayAgain = this.handlePlayAgain.bind(this);
  }

  handlePlayAgain() {
    this.setState({
      buttonVisibility: false,
      visibility: [true, true, true]
    });
  }

  clickitem(user) {
    var url = "http://localhost:4000/generate-random";
    this.setState({ userSelected: user });

    fetch(url)
      .then(response => {
        if (response.status >= 400) {
          throw new Error("Bad response from server");
        }
        return response.json();
      })
      .then(data => {
        var computer = data.item;
        this.setState({ computerSelected: computer });
        if (
          (user === "Rock" && computer === "Scissors") ||
          (user === "Paper" && computer === "Rock") ||
          (user === "Scissors" && computer === "Paper")
        ) {
          this.props.increment();
        } else if (user === computer) {
          this.props.doNothing();
        } else {
          this.props.decrement();
        }

        console.log(user + " " + computer);
        console.log("------------------------------------");

        App.contextTypes = { store: React.PropTypes.object };
        let store = this.context.store;
        console.log(store);

        arrayvar = [];

        var arrayvar = [];
        if (user === "Rock" && computer === "Rock") {
          arrayvar = [true, false, false];
        } else if (user === "Paper" && computer === "Paper") {
          arrayvar = [false, true, false];
        } else if (user === "Scissors" && computer === "Scissors") {
          arrayvar = [false, false, true];
        } else if (
          (user === "Rock" && computer === "Paper") ||
          (user === "Paper" && computer === "Rock")
        ) {
          arrayvar = [true, true, false];
        } else if (
          (user === "Rock" && computer === "Scissors") ||
          (user === "Scissors" || computer === "Rock")
        ) {
          arrayvar = [true, false, true];
        } else if (
          (user === "Paper" && computer === "Scissors") ||
          (user === "Scissors" || computer === "Paper")
        ) {
          arrayvar = [false, true, true];
        }
        this.setState({ visibility: arrayvar });
        this.setState({
          buttonVisibility: true
        });
      });
  }

  render() {
    return (
      <div className="CenterDiv">
        <div className="AppTitle">
          <b>Score: {this.props.score}</b>
          <div>
            {this.state.visibility[0]
              ? <RoundedButton
                  text="Rock"
                  clickitem={this.clickitem}
                  label={
                    this.state.userSelected === "Rock" &&
                      this.state.computerSelected === "Rock"
                      ? "User & Computer Selected"
                      : this.state.userSelected === "Rock"
                        ? "User Selected"
                        : this.state.computerSelected === "Rock"
                          ? "Computer Selected"
                          : ""
                  }
                />
              : null}
            {this.state.visibility[1]
              ? <RoundedButton
                  text="Paper"
                  clickitem={this.clickitem}
                  label={
                    this.state.userSelected === "Paper" &&
                      this.state.computerSelected === "Paper"
                      ? "User & Computer Selected"
                      : this.state.userSelected == "Paper"
                        ? "User Selected"
                        : this.state.computerSelected === "Paper"
                          ? "Computer Selected"
                          : ""
                  }
                />
              : null}
            {this.state.visibility[2]
              ? <RoundedButton
                  text="Scissors"
                  clickitem={this.clickitem}
                  label={
                    this.state.userSelected === "Scissors" &&
                      this.state.computerSelected === "Scissors"
                      ? "User & Computer Selected"
                      : this.state.userSelected === "Scissors"
                        ? "User Selected"
                        : this.state.computerSelected === "Scissors"
                          ? "Computer Selected"
                          : ""
                  }
                />
              : null}
          </div>

          <div className="Status">{this.props.status}</div>

          {this.state.buttonVisibility
            ? <button onClick={this.handlePlayAgain} style={{ margin: 30 }}>
                Play Again
              </button>
            : null}

        </div>
      </div>
    );
  }
}

function mapStateToProps(state) {
  return { score: state.score, status: state.status };
}

export default connect(mapStateToProps, actions)(App);

index.js index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import registerServiceWorker from "./registerServiceWorker";
import "./index.css";

import { Provider } from "react-redux";
import { createStore } from "redux";
import scoreReducer from "./reducers";

let store = createStore(scoreReducer);

ReactDOM.render(
  <Provider store={store}><App /></Provider>,
  document.getElementById("root")
);
registerServiceWorker();

secondcomponent.js secondcomponent.js

export default class SecondComponent extends Component {
  render() {
    return (
       // print score which is in redux
    );
  }
}

third component.js 第三个组件.js

export default class ThirdComponent extends Component {
  render() {
    return (
       // print score which is in redux
    );
  }
}

Whats the way to have an access of redux store in multiple components ? 什么方式可以在多个组件中访问redux存储?

Any component that is wrapped with connect : 使用connect包装的任何组件:

connect(mapStateToProps, actions)(AnyComponent);

will have access to the entire redux store. 将有权访问整个 redux商店。
With mapStateToProps you can pass just relevant piece of data from the redux store to the connected component via props . 随着mapStateToProps您可以从刚刚通过的相关数据块的redux店通过对所连接的组件props

About component internal state , my rule of thumb is to set internal state just for data that is relevant for the specific component. 关于组件内部state ,我的经验法则是仅针对与特定组件相关的数据设置内部状态。
For example, extend or collapse state for a Drop-down. 例如, extendcollapse下拉状态。

As for ajax requests, if you already using redux I highly recommend to use actions with thunks or sagas and pass the new fetched data through the redux flow: 至于ajax请求,如果你已经使用了redux我强烈建议你使用thunkssagas动作,并通过redux流传递新获取的数据:
Action/thunk -> Reducers -> connected components. 动作/ thunk - > Reducers - >连接组件。

Edit 编辑
As a followup to your comment, 作为评论的后续内容,
You don't need to pass every component you want to connect to the Provider, you just pass a root component ( App in your case) and each child of App can connect to redux if necessary: 你并不需要传递要连接到提供每个组件,您只需通过一个根组件( App在你的情况下)和每个孩子App可以连接到redux如果需要的话:

class SecondComponent extends Component {
  render() {
    return (
       // print score which is in redux
       <div>this.props.score</div> 
    );
  }
} 

export default connect(mapStateToProps)(SecondComponent);

And as well as for other components: 以及其他组件:

class ThirdComponent extends Component {
  render() {
    return (
       // print score which is in redux
       <div>this.props.score</div> 
    );
  }
} 

export default connect(mapStateToProps)(ThirdComponent);

Edit #2 编辑#2
As a followup to your other comment: 作为您的其他评论的后续内容:

so passing value in props to components or use above said approach, Idk which is recommended ? 所以将道具中的值传递给组件或使用上述方法,建议使用Idk吗?

Avoid connecting components when you can and pass down the props to the children, the main reason for this is to prevent dependency on redux . 尽可能避免连接组件并将道具传递给孩子,主要原因是为了防止对redux依赖。
I prefer keep my components "dumb" as i can and let them concern only on how things should look. 我更喜欢尽可能让我的组件“哑”,让他们只关注事物的外观。
I do have some components that concern on how things should work and these components are mainly dealing with logic and passing down data to the children, they are the components i often connect. 我确实有一些关于事情应该如何工作的组件,这些组件主要处理逻辑并将数据传递给子节点,它们是我经常连接的组件。

When i notice that my app is scaling and some of my components are acting as a proxy of props (i even got a word for that! "Propxy"), that is they get props from their parent and pass them down without using them, i usually inject a connected component in the middle of the components tree so i can let the "propxy" components down the tree flow be more lighten and slim. 当我注意到我的应用程序正在缩放并且我的一些组件充当道具的代理时(我甚至得到了一个词!“Propxy”),那就是他们从父母那里获得道具并将其传递下来而不使用它们,我通常在组件树的中间注入一个连接组件,这样我就可以让树下流动的“propxy”组件更加轻盈和纤细。

The generic approach of using redux in react applications is use it along with react-redux library. 在反应应用程序中使用redux的通用方法是将其与react-redux库一起使用。 That library provides connect function, which helps to access store in react components in more clean way. 该库提供connect功能,有助于以更干净的方式访问反应组件中的存储。

Instead of trying to access store via context, just use connect function: 而不是尝试通过上下文访问存储,只需使用connect函数:

import { connect } from 'react-redux';

const SecondComponent = ({ score }) => <div>{score}</div>

// with help of `connect`, you are providing `score` prop to `SomeComponent`
// next, you can render that connected component anywhere in your app
export default connect(
  (state) => ({
    score: state.score
  })
)(SecondComponent)

You could use connect for any of your react components such as ThirdComponent ad so on. 您可以对任何反应组件使用connect,例如ThirdComponent ad等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM