簡體   English   中英

道具更改時反應不重新渲染組件

[英]React not rerendering the component when prop changes

我有一個選項列表組件,它根據所選選項呈現一些子項。 當我在兩個選項中渲染相同的組件但使用不同的道具時會出現問題,因為在這種情況下,組件不會使用新道具重新渲染。

讓我澄清一下問題:我有一個選擇列表,我有一個 select 選項“A”,然后在選擇列表下方呈現一個文本組件,我在該文本字段中輸入“錯誤”,然后在選擇列表中輸入 select 選項“B”,然后其他文本字段組件消失,另一個文本字段組件在選項列表下方呈現。 最后一個組件應該被渲染為空,但問題是它包含單詞“error”。

這是重現錯誤的代碼的最小化版本:

import React from "react";

class TextField extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: props.value };
  }

  _onChange = (event) => {
    this.setState({ value: event.currentTarget.value });
  };

  _handleBlur = (event) => {
    this.setState({ value: event.currentTarget.value.trim() });
  };

  render() {
    const { value } = this.state;
    return (
      <div>
        <label>TextField</label>
        <input
          type="text"
          onChange={this._onChange}
          onBlur={this._handleBlur}
          value={value}
        />
      </div>
    );
  }
}

class Picklist extends React.Component {
  constructor(props) {
    super(props);
    this.state = { selectedOption: "" };
    this.options = ["Blank", "A", "B"];
  }

  // eslint-disable-next-line consistent-return
  _handleSelectorCallback = (newOption) => {
    this.setState({ selectedOption: newOption.currentTarget.value });
  };

  _renderChildren(selectedOption) {
    if (!selectedOption) {
      return null;
    }
    if (selectedOption === "A") {
      return <TextField value="optionA"/>;
    }
    if (selectedOption === "B") {
      return <TextField value="optionB"/>;
    }
  }

  _renderOptions() {
    const { selectedOption } = this.state;
    return this.options.map((option) => (
      <option value={option} selected={selectedOption === option}>
        {option}
      </option>
    ));
  }

  render() {
    const { selectedOption } = this.state;
    return (
      <React.Fragment>
        <div>
          <label>Demo of the Error!</label>
          <select
            onChange={this._handleSelectorCallback}
            value={selectedOption}
          >
            {this._renderOptions()}
          </select>
        </div>
        {this._renderChildren(selectedOption)}
      </React.Fragment>
    );
  }
}

export default Picklist;


忽略組件的編寫有多糟糕,只是為了重現我遇到的錯誤。 知道為什么組件沒有用新值重新渲染嗎?

我認為正在發生的事情是,當您從一個<TextField>切換到另一個時,React 試圖通過將不同的道具傳遞給同一個實例來提高效率。 你可以告訴 React 它們是不同的,應該通過添加一個鍵來重新渲染:

_renderChildren(selectedOption) {
    if (!selectedOption) {
      return null;
    }
    if (selectedOption === "A") {
      return <TextField key="A" value="optionA" />;
    }
    if (selectedOption === "B") {
      return <TextField key="B" value="optionB" />;
    }
  }

或者,您可以使您的TextField成為受控組件,這意味着它沒有內部 state,並且 value/onChange fn 作為道具傳入。 我編輯了您的代碼框以遵循此模式: https://codesandbox.io/s/empty-wind-43jq4?file=/src/App.js

我試過你的沙盒。 您的TextField組件不會被卸載,因此它的構造函數只被調用一次。 您所做的與該組件有關的每項更改都會轉到它的componentDidUpdate掛鈎。

所以這就是你所缺少的:

componentDidUpdate() {
   if (this.state.value !== this.props.value) {
     this.setState({ value: this.props.value });
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM