如何在多个组件中共享 redux 存储 [英] How to share redux store in multiple components

查看:19
本文介绍了如何在多个组件中共享 redux 存储的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个组件,我将 redux 集成到我的 React 应用程序中.我正在打开第二个然后第三个组件.我不希望将我在第一个组件中获得的数据传递给 props 中的第二个然后第三个.

我想使用 redux store 来做到这一点.有没有办法做到这一点?

App.js

import React, { Component } from "react";从./logo.svg"导入标志;导入./App.css";从./RoundedButton"导入圆形按钮;从react-redux"导入{连接};从redux"导入 { bindActionCreators };从./actions/index"导入 * 作为动作;类 App 扩展组件 {构造函数(道具){超级(道具);this.state = {得分:0,地位: "",用户选择:"",计算机已选择:"",可见性:[真,真,真],按钮可见性:false};this.clickitem = this.clickitem.bind(this);this.handlePlayAgain = this.handlePlayAgain.bind(this);}handlePlayAgain() {this.setState({按钮可见性:假,可见性:[真,真,真]});}点击项目(用户){var url = "http://localhost:4000/generate-random";this.setState({ userSelected: 用户 });获取(网址).then(响应 => {如果(响应状态> = 400){throw new Error("来自服务器的错误响应");}返回 response.json();}).then(数据=> {var computer = data.item;this.setState({ computerSelected: 计算机 });如果 ((用户 === "摇滚" && 计算机 === "剪刀") ||(用户===纸"&&计算机===摇滚")||(用户===剪刀"&&计算机===纸")){this.props.increment();} else if (user === 计算机) {this.props.doNothing();} 别的 {this.props.decrement();}console.log(用户 + " " + 电脑);console.log("------------------------------------");App.contextTypes = { store: React.PropTypes.object };让商店= this.context.store;控制台日志(商店);数组变量 = [];var arrayvar = [];if (user === "Rock" && computer === "Rock") {arrayvar = [真,假,假];} else if (user === "Paper" && computer === "Paper") {arrayvar = [假,真,假];} else if (user === "剪刀" && 电脑 === "剪刀") {arrayvar = [假,假,真];}否则如果((用户 ===摇滚"&& 计算机 ===纸")||(用户===纸"&&计算机===摇滚")){arrayvar = [真,真,假];}否则如果((用户 === "摇滚" && 计算机 === "剪刀") ||(用户===剪刀"||计算机===摇滚")){arrayvar = [真,假,真];}否则如果((用户===纸"&&计算机===剪刀")||(用户===剪刀"||计算机===纸")){arrayvar = [假,真,真];}this.setState({可见性:arrayvar });this.setState({按钮可见性:true});});}使成为() {返回 (<div className="CenterDiv"><div className="AppTitle"><b>分数:{this.props.score}</b><div>{this.state.visibility[0]?<圆形按钮文字=摇滚"clickitem={this.clickitem}标签={this.state.userSelected === "摇滚" &&this.state.computerSelected === "摇滚"?用户和计算机选择": this.state.userSelected === "摇滚"?用户选择": this.state.computerSelected === "摇滚"?已选择计算机":""}/>: 空值}{this.state.visibility[1]?<圆形按钮文字=纸"clickitem={this.clickitem}标签={this.state.userSelected ===论文"&&this.state.computerSelected === "纸"?用户和计算机选择": this.state.userSelected == "Paper"?用户选择": this.state.computerSelected === "纸"?已选择计算机":""}/>: 空值}{this.state.visibility[2]?<圆形按钮文字=剪刀"clickitem={this.clickitem}标签={this.state.userSelected ===剪刀"&&this.state.computerSelected === "剪刀"?用户和计算机选择": this.state.userSelected === "剪刀"?用户选择": this.state.computerSelected === "剪刀"?已选择计算机":""}/>: 空值}

<div className="Status">{this.props.status}</div>{this.state.buttonVisibility?<button onClick={this.handlePlayAgain} style={{ margin: 30 }}>再玩一遍: 空值}

);}}函数 mapStateToProps(state) {返回 { 分数:state.score,状态:state.status };}导出默认连接(mapStateToProps,动作)(应用程序);

index.js

从react"导入React;从react-dom"导入 ReactDOM;从./App"导入应用程序;从./registerServiceWorker"导入 registerServiceWorker;导入./index.css";从react-redux"导入{提供者};import { createStore } from "redux";从./reducers"导入scoreReducer;让 store = createStore(scoreReducer);ReactDOM.render(<Provider store={store}><App/></Provider>,document.getElementById("root"));注册服务工作者();

secondcomponent.js

export default class SecondComponent extends Component {使成为() {返回 (//打印 redux 中的分数);}}

第三个组件.js

export default class ThirdComponent extends Component {使成为() {返回 (//打印 redux 中的分数);}}

在多个组件中访问 redux store 的方法是什么?

解决方案

Anyconnect 包装的组件:

connect(mapStateToProps, actions)(AnyComponent);

将可以访问整个 redux 商店.
使用mapStateToProps,您可以通过propsredux 存储中的相关数据传递给连接的组件.

关于组件内部 state,我的经验法则是只为与特定组件相关的数据设置内部状态.
例如,下拉菜单的 extendcollapse 状态.

对于 ajax 请求,如果你已经在使用 redux,我强烈建议使用带有 thunkssagas 的操作> 并通过 redux 流传递新获取的数据:
Action/thunk -> Reducers -> 连接组件.

编辑
作为您评论的后续行动,
您不需要将要连接的每个组件都传递给 Provider,您只需传递一个根组件(在您的情况下为 App),并且 App 的每个子组件都可以连接如有必要,redux:

class SecondComponent 扩展组件 {使成为() {返回 (//打印 redux 中的分数<div>this.props.score</div>);}}导出默认连接(mapStateToProps)(第二组件);

以及其他组件:

class ThirdComponent 扩展组件 {使成为() {返回 (//打印 redux 中的分数<div>this.props.score</div>);}}导出默认连接(mapStateToProps)(第三组件);

编辑 #2
作为您其他评论的后续:

<块引用>

因此将道具中的值传递给组件或使用上述方法,idk 推荐哪个?

尽可能避免连接组件并将 props 传递给孩子,这样做的主要原因是为了防止对 redux 的依赖.
我更喜欢让我的组件尽可能愚蠢",让他们只关心事情的样子.
我确实有一些关注事物应该如何工作的组件,这些组件主要处理逻辑并将数据传递给孩子,它们是我经常连接的组件.

当我注意到我的应用程序正在扩展并且我的一些组件充当 props 的代理时(我什至有一个词!Propxy"),也就是说它们从它们的父级获取 props 并在没有使用它们,我通常会在组件树的中间注入一个连接的组件,这样我就可以让树流下的propxy"组件更轻更薄.

Hi I have one component in which I integrated the redux in my react application. 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. Is there any way to do this ?

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

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

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

third component.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 ?

解决方案

Any component that is wrapped with connect:

connect(mapStateToProps, actions)(AnyComponent);

will have access to the entire redux store.
With mapStateToProps you can pass just relevant piece of data from the redux store to the connected component via props.

About component internal state, my rule of thumb is to set internal state just for data that is relevant for the specific component.
For example, extend or collapse state for a Drop-down.

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:
Action/thunk -> Reducers -> connected components.

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:

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
As a followup to your other comment:

so passing value in props to components or use above said approach, Idk which is recommended ?

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

这篇关于如何在多个组件中共享 redux 存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆