Передача состояния между компонентами - PullRequest
0 голосов
/ 25 декабря 2018

Я написал компонент с состоянием 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 голосов
/ 25 декабря 2018

Общий родитель: (Вы можете поднять свое состояние на один уровень выше)

Если у этих компонентов есть общий родительский элемент, то вам нужно переместить это состояние на один шаг вверх в общего родителя.компонента и передать обработчик для обновления состояния в 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

0 голосов
/ 25 декабря 2018

Как уже упоминалось, распространенным способом совместного использования состояния между компонентами является использование Redux, MobX является еще одной альтернативой.

Вот базовый пример приложения Redux.Два компонента, один из которых записывает значение в хранилище Redux, а другой - считывает значение из хранилища Redux.

Ключевые части настройки Redux:

  • <Provider> - Это оборачивает все ваше приложение и предоставляет хранилище, также известное как редуктор
  • reducer - Здесь вы устанавливаете начальное состояние и возвращаете обновленную версию состояния на основе действий
  • actions - Действия - это просто объекты со значениями, из которых вы можете прочитать, чтобы обновить и вернуть новое состояние
  • connect - Эта функция соединяет ваш компонент с приставкой, первые два аргумента - mapStateToProps и mapDispatchToProps
  • mapStateToProps - Этот параметр представляет собой функцию, которая позволяет читать из состояния (хранилище с избыточностью) и помещает значения в this.props
  • mapDispatchToProps -Отсюда действия по обновлению хранилища выполняются

Ваши редуктор, действия и селекторы обычно находятся в отдельных файлах, поэтому их можно легко разделить между компонентами.

КомпонентНиже приведены также отдельные файлы, и вы будете export default connect часть каждого.

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.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/6.0.0/react-redux.min.js"></script>
<div id="root"></div>
0 голосов
/ 25 декабря 2018

Вы можете попробовать любую из следующих вещей

a.Переместите состояние в общий родительский компонент GenreSelectPage и InRoomPage.Передайте метод handleGenereChange в GenreSelectPage в качестве реквизита и установите состояние в parentComponent.Отправьте значение состояния в качестве реквизита на InRoomPage.Это называется поднятием состояния.Более подробная информация на https://reactjs.org/docs/lifting-state-up.html

б.Используйте Redux.Более подробная информация доступна на https://almerosteyn.com/2016/08/redux-explained-again

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...