最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to share redux store in multiple components - Stack Overflow

programmeradmin0浏览0评论

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.stateputerSelected === "Rock"
                      ? "User & Computer Selected"
                      : this.state.userSelected === "Rock"
                        ? "User Selected"
                        : this.stateputerSelected === "Rock"
                          ? "Computer Selected"
                          : ""
                  }
                />
              : null}
            {this.state.visibility[1]
              ? <RoundedButton
                  text="Paper"
                  clickitem={this.clickitem}
                  label={
                    this.state.userSelected === "Paper" &&
                      this.stateputerSelected === "Paper"
                      ? "User & Computer Selected"
                      : this.state.userSelected == "Paper"
                        ? "User Selected"
                        : this.stateputerSelected === "Paper"
                          ? "Computer Selected"
                          : ""
                  }
                />
              : null}
            {this.state.visibility[2]
              ? <RoundedButton
                  text="Scissors"
                  clickitem={this.clickitem}
                  label={
                    this.state.userSelected === "Scissors" &&
                      this.stateputerSelected === "Scissors"
                      ? "User & Computer Selected"
                      : this.state.userSelected === "Scissors"
                        ? "User Selected"
                        : this.stateputerSelected === "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 ?

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 ?

Share Improve this question asked Oct 17, 2017 at 18:58 N SharmaN Sharma 34.5k98 gold badges265 silver badges452 bronze badges 6
  • There is a whole bunch of react-redux tutorials for that. – lilezek Commented Oct 17, 2017 at 19:01
  • That's not a good practice – Alex W Commented Oct 17, 2017 at 19:02
  • You are using an awful lot of state in your component. The reason for using Redux and mapStateToProps is to use props in your render. – mhatch Commented Oct 17, 2017 at 19:04
  • @AlexW so fetch value from store in a different components is not a good practice ? – N Sharma Commented Oct 17, 2017 at 19:12
  • I am a bit confused, why don't pass those as props or just make Second and Third Component connected components? – Chen Commented Oct 17, 2017 at 19:18
 |  Show 1 more comment

2 Answers 2

Reset to default 15

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.

The generic approach of using redux in react applications is use it along with react-redux library. That library provides connect function, which helps to access store in react components in more clean way.

Instead of trying to access store via context, just use connect function:

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.

发布评论

评论列表(0)

  1. 暂无评论