React не обновляет реквизиты компонента, переданного как реквизиты - PullRequest
0 голосов
/ 21 апреля 2019

У меня есть React DOM, который выглядит так:

DOM structure

В состоянии MarketDepthWindow у меня есть isBackgroundEnabled, который я хочу передать как реквизит AskOrdersTab. Но он проходит только начальный реквизит и не обновляется. Оно должно обновляться при нажатии кнопки MarketDepthHeaderComponent.

Я предполагаю, что проблема в том, что я передаю это как опору TabsContainer.

Я пытался изменить React.Component на React.PureComponent, используя shouldComponentUpdate(), добавив React.cloneElement и пропуская реквизиты через TabsContainer, но у меня ничего не работает.

Может, я допустил какую-то архитектурную ошибку? Может быть, мне стоит как-нибудь использовать ссылки?

class AskOrdersTab extends React.Component {
  render() {
    return <div>bids</div>
  }
}

class BidOrdersTab extends React.Component {
  render() {
    return <div>asks</div>
  }
}

class MarketDepthHeaderComponent extends React.Component {
  render() {
    return <button class={this.props.isBackgroundEnabled ? 'active' : ''} onClick={this.props.handleBackgroundButtonClick}></button>
  }
}

class TabsContainer extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      tabs: props.tabs.tabs || [],
      tabHeaderComponent: props.tabs.tabHeaderComponent || ''
    }
  }

  renderComponents() {
    let tabsComponents = [];
    for (let tab of this.state.tabs.length) {
      tabsComponents.push(
        <div>{tab.component}</div>
      )
    }
    return tabsComponents;
  }

  render() {
    return (
      <>
        {this.state.tabHeaderComponent}
        {this.renderComponents()}
      </>
    );
  }
}

class MarketDepthWindow extends React.Component {

  handleBackgroundButtonClick = (event) => {
    this.setState((prevState) => ({
      isBackgroundEnabled: !prevState.isBackgroundEnabled
    }))
  }

  constructor(props) {
    super(props)
    this.state = {
      isBackgroundEnabled: true,
      handleBackgroundButtonClick: this.handleBackgroundButtonClick
    }
  }

  render() {
    let tabsProps = {
      tabs: [
        { title: 'Bid', component: <BidOrdersTab {...this.state} /> },
        { title: 'Ask', component: <AskOrdersTab {...this.state} /> }
      ],
      tabHeaderComponent: <MarketDepthHeaderComponent {...this.state} />
    }
    return <TabsContainer tabs={tabsProps} isBackgroundEnabled={this.state.isBackgroundEnabled} />
  }
}

ReactDOM.render(
  <MarketDepthWindow />,
  document.getElementById("market-depth-window")
);

Ответы [ 2 ]

1 голос
/ 21 апреля 2019

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

import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";

class AskOrdersTab extends React.Component {
  render() {
    return <div>bids</div>;
  }
}

class BidOrdersTab extends React.Component {
  render() {
    return <div>asks</div>;
  }
}

class MarketDepthHeaderComponent extends React.Component {
  render() {
    return (
      <button onClick={this.props.onClick}>
        {this.props.isBackgroundEnabled ? "enabled" : "disabled"}
      </button>
    );
  }
}

class TabsContainer extends React.Component {
  renderComponents() {
    let tabsComponents = [];
    for (let tab of this.props.tabs.tabs) {
      tabsComponents.push(<div key={tab.title}>{tab.component}</div>);
    }
    return tabsComponents;
  }

  render() {
    return (
      <>
        {this.props.tabs.tabHeaderComponent}
        {this.renderComponents()}
      </>
    );
  }
}

class MarketDepthWindow extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isBackgroundEnabled: true
    };
  }

  handleBackgroundButtonClick = () => {
    this.setState({
      isBackgroundEnabled: !this.state.isBackgroundEnabled
    });
  };

  render() {
    let tabsProps = {
      tabs: [
        { title: "Bid", component: <BidOrdersTab {...this.state} /> },
        { title: "Ask", component: <AskOrdersTab {...this.state} /> }
      ],
      tabHeaderComponent: (
        <MarketDepthHeaderComponent
          onClick={this.handleBackgroundButtonClick}
          isBackgroundEnabled={this.state.isBackgroundEnabled}
        />
      )
    };
    return (
      <TabsContainer
        tabs={tabsProps}
        isBackgroundEnabled={this.state.isBackgroundEnabled}
      />
    );
  }
}

const rootElement = document.getElementById("market-depth-window");
ReactDOM.render(<MarketDepthWindow />, rootElement);

Это ваша демонстрационная версия, вы можете проверить исправление иубедитесь, что это работает.Удачи

1 голос
/ 21 апреля 2019

Простой ответ на ваш вопрос заключается в том, что вы храните AskOrdersTab в состоянии TabsContainer, и в вашем случае вы хотите получить к нему доступ через реквизит.

Объяснение: Это вызвано тем, что всякий раз, когда ваш компонент обновляется, что он делает, TabsContainer все равно будет отображать исходный AskOrdersTab (это связано с состоянием AskOrdersTab и текущей версией с обновленными реквизитами. тот же объект). Есть обходные пути для такого поведения с использованием ловушек жизненного цикла, а именно getDerivedStateFromProps. Но в этом случае я бы не советовал.

TL; DR замените ваш TabsContainer на этот, и он должен работать.

class TabsContainer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      tabHeaderComponent: props.tabs.tabHeaderComponent || '',
    };
  }

  renderComponents() {
    let tabsComponents = [];
    for (let tab of this.props.tabs.tabs) {
      tabsComponents.push(<div>{tab.component}</div>);
    }
    return tabsComponents;
  }

  render() {
    return (
      <>
        {this.state.tabHeaderComponent}
        {this.renderComponents()}
      </>
    );
  }
}

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

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