组件之间的传递状态

时间:2018-12-25 07:29:00

标签: javascript reactjs react-component

我编写了一个状态为chosenGenre的组件,在其中,有一个函数可以根据所单击的按钮更改状态。

我想获取更新后的状态(即string)并在其他组件中使用它。

这是声明状态的组件:

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>
        ) 
     }
}

这是我想使用chosenGenre组件中的GenreSelectPage状态的新组件:

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

export default class InRoomPage extends Component {

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

我应该在以下内容中进行哪些更改:

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

那么它将起作用吗?

3 个答案:

答案 0 :(得分:2)

共同的父母:(您可以将状态提高一级)

如果这些组件具有一个公共父组件,那么您需要将此状态向上移动到公共父组件中,并传递处理程序以将状态更新为GenreSelectPage并传递状态为props进入InRoomPage

没有共同的父母 :(可以使用Redux)

您需要使用 Redux ,在那里您声明将保留在一个中央存储中,并且可以从组件树的任何部分从任何组件连接到该存储。并将状态变成道具。

用法:https://redux.js.org/basics/usage-with-react

将组件移到同一父对象下:

您可以创建一个名为 componentParent 的新组件(根据您的应用使用名称),将状态存储在该组件中。

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

export default class componentParent 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>
      )
    }
}

也请检查Context API

答案 1 :(得分:0)

您可以尝试以下任何操作

a。将状态移至GenreSelectPageInRoomPage的公共父组件。将handleGenereChange方法传递给GenreSelectPage作为道具,并在parentComponent中设置状态。将状态值作为道具发送到InRoomPage。这称为提升状态。有关更多详细信息,请访问https://reactjs.org/docs/lifting-state-up.html

b。使用Redux。有关https://almerosteyn.com/2016/08/redux-explained-again

的更多信息

答案 2 :(得分:0)

正如其他人所提到的,在组件之间共享状态的常见方法是使用Redux,MobX是另一种选择。

这是Redux应用程序的基本示例。有两个组件,一个组件将值写入Redux存储,另一个组件从Redux存储读取值。

设置Redux的关键部分是:

  • <Provider>-包装您的整个应用并为商店提供商品,也称为简化器
  • reducer-在这里设置初始状态,并根据操作返回状态的更新版本
  • 动作-动作只是具有可读取值以更新和返回新状态的对象
  • connect-此函数将您的组件连接到redux,其前两个参数为mapStateToPropsmapDispatchToProps
  • mapStateToProps-此参数是允许您从状态(redux存储)中读取的函数,它将把值放入this.props
  • mapDispatchToProps-从此处完成更新商店的调度动作

减速器,动作和选择器通常位于单独的文件中,因此可以轻松地在组件之间共享它们。

下面的组件也将放在单独的文件中,并且您将export default的{​​{1}}部分。

演示

connect
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')
);