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

javascript - Passing state between components - Stack Overflow

programmeradmin5浏览0评论

I wrote a ponent with a state chosenGenre and inside it, there is a function that changes the state according to the clicked button.

I would like to take the updated state (which is string) and use it in another ponent.

This is the ponent in which the state is declared:

import React, { Component } from 'react';
import Genre from './Genre';
import './GenreSelectPage.css';
import Blues from '../Blues.png';
import Classical from '../Classical.png'; 
import Country from '../Country.png';

export default class GenreSelectPage extends Component{

    state = {
        chosenGenre: ""
    }

    handleClick = (genreName) => {
        this.setState({ chosenGenre: genreName });
    }

    render() {
        return(
        <div className = "GenreSelectPage">
        <h3>Select your desired Kollab Room Genre</h3>
        <Genre genrePicture= {Blues} genreClicked = {()=>this.handleClick("Blues")}/>
        <Genre genrePicture= {Classical} genreClicked = {()=>this.handleClick("Classical")}/>
        <Genre genrePicture= {Country} genreClicked = {()=>this.handleClick("Country")}/>
        </div>
        ) 
     }
}

And this is the new ponent for which I want to use the chosenGenre state from GenreSelectPage ponent :

import React, { Component } from 'react';
import GenreSelectPage from './GenreSelectPage';

export default class InRoomPage extends Component {

    render() {
        return(
            <div className = "InRoomPage">
                <p>Wele to {GenreSelectPage.state.chosenGenre} page</p>
            </div>
        )
    }
}

What should I change inside the:

<p>Wele to {GenreSelectPage.state.chosenGenre} room !</p>

So it will work?

I wrote a ponent with a state chosenGenre and inside it, there is a function that changes the state according to the clicked button.

I would like to take the updated state (which is string) and use it in another ponent.

This is the ponent in which the state is declared:

import React, { Component } from 'react';
import Genre from './Genre';
import './GenreSelectPage.css';
import Blues from '../Blues.png';
import Classical from '../Classical.png'; 
import Country from '../Country.png';

export default class GenreSelectPage extends Component{

    state = {
        chosenGenre: ""
    }

    handleClick = (genreName) => {
        this.setState({ chosenGenre: genreName });
    }

    render() {
        return(
        <div className = "GenreSelectPage">
        <h3>Select your desired Kollab Room Genre</h3>
        <Genre genrePicture= {Blues} genreClicked = {()=>this.handleClick("Blues")}/>
        <Genre genrePicture= {Classical} genreClicked = {()=>this.handleClick("Classical")}/>
        <Genre genrePicture= {Country} genreClicked = {()=>this.handleClick("Country")}/>
        </div>
        ) 
     }
}

And this is the new ponent for which I want to use the chosenGenre state from GenreSelectPage ponent :

import React, { Component } from 'react';
import GenreSelectPage from './GenreSelectPage';

export default class InRoomPage extends Component {

    render() {
        return(
            <div className = "InRoomPage">
                <p>Wele to {GenreSelectPage.state.chosenGenre} page</p>
            </div>
        )
    }
}

What should I change inside the:

<p>Wele to {GenreSelectPage.state.chosenGenre} room !</p>

So it will work?

Share Improve this question edited Dec 25, 2018 at 12:13 Anas Abu Farraj 1,5984 gold badges23 silver badges32 bronze badges asked Dec 25, 2018 at 7:28 jrzjrz 1,3876 gold badges31 silver badges73 bronze badges 6
  • What is the relation between the above two ponents? do they have same parent ponent? – Abhay Sehgal Commented Dec 25, 2018 at 7:32
  • Do these ponents share a mon parent? or these ponents have different parents? – Praveen Rao Chavan.G Commented Dec 25, 2018 at 7:35
  • paste your Genre ponent code too. – Vikramaditya Commented Dec 25, 2018 at 7:35
  • They do not have the same parent. – jrz Commented Dec 25, 2018 at 7:38
  • are these two different pages? – Amit Chauhan Commented Dec 25, 2018 at 7:46
 |  Show 1 more ment

3 Answers 3

Reset to default 9

Common parent: ( You can lift your state up one level )

If these ponents have a mon parent, then you need to move this state one step up into the mon parent ponent and pass the handler to update the state into GenreSelectPage and pass the state has props into InRoomPage.

Have no mon parent: ( Can use Redux )

You need to use Redux, where you state will be maintained in one central store and you can connect to this store from any ponent from any part of the ponent tree and get the state into its props.

usage : https://redux.js/basics/usage-with-react

Moving ponents under the same parent:

You can create a new ponent say ponentParent (Use name according to your app ), store your state in this ponent.

import React, { Component } from 'react';
import GenreSelectPage from './GenreSelectPage';
import InRoomPage from './InRoomPage';

export default class ponentParent extends Component {

    state = {
      chosenGenre: ""
    }

    handleClick = (genreName) => {
      this.setState({ chosenGenre: genreName });
    }

    render() {
      return(
        <div className = "InRoomPage">
          <GenreSelectPage clickHandler={this.handleClick}></GenreSelectPage>
          <InRoomPage chosenGenre={this.state.chosenGenre}></InRoomPage>
        </div>
      )
    }
}

also please check Context API

As others have mentioned, the mon way to share state between ponents is to use Redux, MobX is another alternative.

Here's a basic example of a Redux application. Two ponents, one which writes a value to the Redux store, and the other which reads a value from the Redux store.

The key parts of setting up Redux are:

  • <Provider> - This wraps your entire app and supplies the store, also known as a reducer
  • reducer - This is where you set an initial state, and return an updated version of the state based on actions
  • actions - Actions are just objects with values you can read from to update and return a new state
  • connect - This function connects your ponent to redux, its first two arguments are mapStateToProps, and mapDispatchToProps
  • mapStateToProps - This parameter is a function that allows you to read from the state (redux store), and it will put the values into this.props
  • mapDispatchToProps - Dispatch actions to update the store is done from here

Your reducer, actions, and selectors are normally in separate files, so they can be shared between ponents easily.

The ponents below would be in separate files as well, and you'd export default the connect portion of each.

Demo

const { Component } = React;
const { applyMiddleware, createStore } = Redux;
const { connect, Provider } = ReactRedux;


/*********************/
/** GenreSelectPage **/
/*********************/
class GenreSelectPage extends Component {
  constructor(props) {
    super(props);
    this.selectGenre = this.selectGenre.bind(this);
  }
  selectGenre(e) {
    const genre = e.target.value;
    this.props.selectGenre(genre);
  }
  render() {
    return (
      <div>
        <h3>GenreSelectPage Component</h3>
        <select onChange={this.selectGenre}>
          <option value="">Select a genre</option>
          <option value="blues">Blues</option>
          <option value="classical">Classical</option>
          <option value="country">Country</option>
        </select>
      </div>
    )
  }
}

// Write to store
const mapDispatchToProps = (dispatch) => ({ selectGenre: (genre) => dispatch({type: 'SELECT_GENRE', genre}) })

// Connect to store
const GenreSelectComponent = connect(null, mapDispatchToProps)(GenreSelectPage);


/*******************/
/**  InRoomPage   **/
/*******************/
class InRoomPage extends Component {
  render() {
    return (
      <div>
        <h3>InRoomPage Component</h3>
        <p>{this.props.genre}</p>
      </div>
    )
  }
}

// Read from store
const mapStateToProps = (state) => ({ genre: state.genre });
// Connect to store
const InRoomComponent = connect(mapStateToProps)(InRoomPage);

/*******************/
/**     REDUX     **/
/*******************/
const INITIAL_STATE = {
  genre: null
}
const reducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case 'SELECT_GENRE':
      return {
        ...state,
        genre: action.genre
      }
    default:
      return state;
  }
};
const store = createStore(reducer);

// Provider (from Redux) wraps around your entire app
ReactDOM.render(
  <Provider store={store}>
    <GenreSelectComponent />
    <InRoomComponent />
  </Provider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare./ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/redux/4.0.1/redux.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-redux/6.0.0/react-redux.min.js"></script>
<div id="root"></div>

You can try any of the below things

a. Move the state to the mon parent ponent of GenreSelectPage and InRoomPage. Pass the handleGenereChange method to the GenreSelectPage as props and set the state in the parentComponent. Send the state value as props to InRoomPage. This is called lifting the state up. More details at https://reactjs/docs/lifting-state-up.html

b. Use Redux. More info available on https://almerosteyn./2016/08/redux-explained-again

发布评论

评论列表(0)

  1. 暂无评论