Обновление состояния одного компонента из другого в ReactJS

Я слежу за этой статьей (оригинальная реализация Sibling Sibling): Обновить перекрестный компонент состояния

Пример работает отлично. Но когда я пытаюсь разделить каждый класс на каждый файл .js, а затем использую импорт / экспорт для вызова / связывания друг друга. Он (состояние обновления) больше не работает. Структура такая:

Sibling1.js

import React, { Component } from 'react';
<-- some declare style -->

export function updateText(text) {
  this.setState({text})
}

export class Sibling1 extends Component {
  render() {
    return (
      <div>
        <div style = {{ ...style.topLabel, color: secondaryColor }}>I am Sibling 1</div>
        <input style = {style.textBox} type = "text"
               placeholder = "Write text" onChange = {(e) => updateText(e.target.value)} />
      </div>
    )
  }
} 

Example.js

import React, { Component } from 'react';
import * as sibling1 from './Sibling1'; //is this good?
import {Sibling1} from './Sibling1';    //is this good?

<-- some declare style, variable -->

class Sibling2 extends Component {
  constructor(props) {
    super(props)
    this.state = {
      text: "Initial State"
    }
    sibling1.updateText = sibling1.updateText.bind(this)  //is this good binding?
  }
  render() {
    console.info('Sibling2.state : ', this.state);
    return (
      <div>
        <div style = {{ ...style.topLabel, color: primaryColor }}>I am Sibling 2</div>
        <div style = {style.label}>{this.state.text}</div>
      </div>
    )
  }
}

class Example3 extends Component {
  render() {
    return (
      <div>
        <Sibling1 />
        <Sibling2 />
      </div>
    )
  }
}

export default Example3;

Я просто ожидаю, что Sibling1 может изменить состояние Sibling2 (как и исходная реализация), но не могу. Я предполагаю, что мой привязать (это) не связывает правильный контекст. Может ли кто-нибудь сказать мне, в чем разница между исходной реализацией (статья выше) и моим подходом (отдельно для файлов с несколькими .js)?

Как вы думаете, что будет this в извлеченной функции updateText в файле Sibling1.js? Это должна быть функция в компоненте, а не случайная, плавающая функция. Мне не ясно, что вы пытаетесь сделать или почему ваше состояние даже в Sibling2, если вам нужно обновить его таким образом - похоже, что оно должно быть в Example3, а реквизиты функций переданы в Sibling1. Или вообще переключите управление состоянием и используйте что-то вроде Redux и т. д.

Dave Newton 24.10.2018 17:40

@DaveNewton: Я ожидаю, что состояния Sibling2 также меняются каждый раз, когда я ввожу строку в Sibling1.

nmDat 24.10.2018 17:58

Тогда я поступил бы так, как я предлагал; состояние, по-видимому, принадлежит Example3, модифицируется Sibling1 и потребляется Sibling2. Есть ли явная причина сохранить состояние в Sibling2?

Dave Newton 24.10.2018 18:08
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
3
151
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

updateText() должен быть привязан к компоненту. Я не уверен, чего вы здесь пытаетесь достичь, но updateText() может не работать в Sibling1, если контекст изменится.

Вы можете попробовать привязать updateText() в обоих компонентах (уже связанных в Sibling2).

import React, { Component } from 'react';

export function updateText(text) {
  this.setState({text})
}

export class Sibling1 extends Component {
  constructor() {
    updateText = updateText.bind(this)
  }
  render() {
    return (
      <div>
        <div style = {{ ...style.topLabel, color: secondaryColor }}>I am Sibling 1</div>
        <input style = {style.textBox} type = "text"
               placeholder = "Write text" onChange = {(e) => updateText(e.target.value)} />
      </div>
    )
  }
}

Обычно состояние контролируется в родительском компоненте, если два дочерних компонента должны совместно использовать состояние, а потомкам передается только обработчик.

Ответ принят как подходящий

React как бы заставляет вас использовать односторонний поток данных. Таким образом, вы не можете просто обновить состояние Sibling1 из Sibling2.

Как упоминает Динеш Пандиян в своем примере, у вас обычно есть родительский компонент, который контролирует состояние обоих братьев и сестер. Тогда ваш код будет выглядеть так:

Sibling1.js

import React, { Component } from 'react';
<-- some declare style -->

export class Sibling1 extends Component {
  function updateText(text) {
    // Use updateText function from props.
    // Props are like state but not controlled by the component itself
    // The value is passed to the component from outside
    this.props.updateText(text)
  }

  render() {
    return (
      <div>
        <div style = {{ ...style.topLabel, color: secondaryColor }}>I am Sibling 1</div>
        <input style = {style.textBox} type = "text"
               placeholder = "Write text" 
               onChange = {(e) => this.updateText(e.target.value).bind(this)} />
      </div>
    )
  }
} 

Example.js

import React, { Component } from 'react';
import { Sibling1 } from './Sibling1';    // This is good.
import Sibling1 from './Sibling1'; // This is also possible if you use export default class instead of export class

<-- some declare style, variable -->

class Sibling2 extends Component {
  // Use same function as in Sibling1.
  function updateText(text) {
      this.props.updateText(text)
  }

  render() {
    return (
      <div>
        <div style = {{ ...style.topLabel, color: primaryColor }}>I am Sibling 2</div>
        <div style = {style.label}>{this.props.text}</div> // changed state to props
      </div>
    )
  }
}

class Example3 extends Component {
  constructor(props) {
    super(props);


    this.state = {
      text: "Initial state"
    };
  }

  // Control state from parent component
  function updateText(
    this.setState({ text: text });
  }

  render() {
    return (
      <div>
        <Sibling1 updateText = {this.updateText.bind(this)}/>
        <Sibling2 updateText = {this.updateText.bind(this)} text = {this.state.text} />
      </div>
    )
  }
}

export default Example3;

Другие вопросы по теме