无法在状态更改时重新呈现React组件的地图

时间:2019-11-17 21:15:20

标签: javascript reactjs

我有一个设置,其中有一个需要在视图中显示的React组件图。

也有许多输入选择处理程序会更新父组件的状态,但是在状态更新后,将调用“父组件”渲染方法,但子组件不会刷新“值”。

我在这里想念什么?我有点困惑

问题Stackblitz的最小复制。

import React, { PureComponent } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';

export const ReactExample = ({ name, value, handleChange }) => (
  <select name={name} value={value} onChange={handleChange}>
    <option value="A">Apple</option>
    <option value="B">Banana</option>
    <option value="C">Cranberry</option>
  </select>
)

const Section = props => {
  return (
    <div>
      {props.header}
      <br />
      {props.primaryNode}
      <br />
      {props.bottom}
    </div>
  );
};


class App extends React.PureComponent {

  state = {
    current: 'B'
  };
  constructor(props) {
    super(props);
  }

  show = [5, 6, 3, 5, 7, 8, 77, 8, 90];

  primaryNode = () => {
    const filterData = this.show;

    return (<div>{filterData}----{this.state.current} // doesn't get updated even though state updates after dropdown</div>);
  };

  bottom = () => {
    return (
      <ReactExample name="fruit" value={this.state.current} handleChange={this.handleChange} />

    )
  }

  handleChange = (event) => {
    console.log(event.target.value); // always logged and state updated with no change in value
    this.setState({ current: event.target.value });
  }

  data = ["A", "B", "C"];

  map = {
    "A": (<Section primaryNode={this.primaryNode()} bottom={this.bottom()} header={"A"} />),
    "B": (<Section primaryNode={this.primaryNode()} header={"B"} />),
    "C": (<Section primaryNode={this.primaryNode()} header={"C"} />)
  };

  render() {
    return (<div>{this.data.map(d => this.map[d])}</div>)
  }
}

render(<App />, document.getElementById('root'));

4 个答案:

答案 0 :(得分:1)

我认为通过将所有这些值作为类属性来保存,这比需要使它更加混乱。它们不更新的原因是因为this.map仅定义了一次。您根本不需要地图,只需在render函数内部直接渲染节点即可,该函数在状态更改时被调用:

render() {
  return (
    <div>
      <Section primaryNode={this.primaryNode()} bottom={this.bottom()} header={"A"} />
      <Section primaryNode={this.primaryNode()} header={"B"} />
      <Section primaryNode={this.primaryNode()} header={"C"} />
    </div>
  )
}

如果您真的希望它成为地图,请在render内定义它:

render() {
  const map = {
    "A": <Section primaryNode={this.primaryNode()} bottom={this.bottom()} header={"A"} />,
    "B": <Section primaryNode={this.primaryNode()} header={"B"} />,
    "C": <Section primaryNode={this.primaryNode()} header={"C"} />
  };

  return <div>{this.data.map(d => map[d])}</div>
}

答案 1 :(得分:1)

在第一次渲染组件时,仅一次初始化类字段map。更改状态并不重要,该变量保存的数据完全相同,并且不会随时间变化。

解决方案之一是将该变量移至render中:

render() {
    const map = {
        "A": (<Section primaryNode={this.primaryNode()} bottom={this.bottom()} header={"A"} />),
        "B": (<Section primaryNode={this.primaryNode()} header={"B"} />),
        "C": (<Section primaryNode={this.primaryNode()} header={"C"} />)
    };

    return (<div>{this.data.map(d => this.map[d])}</div>)
}

或者您可以将map字段转换为方法:

map = () => ({
    "A": (<Section primaryNode={this.primaryNode()} bottom={this.bottom()} header={"A"} />),
    "B": (<Section primaryNode={this.primaryNode()} header={"B"} />),
    "C": (<Section primaryNode={this.primaryNode()} header={"C"} />)
});

render() {
    return (<div>{this.data.map(d => this.map()[d])}</div>)
}

因此map返回的数据始终是最新的。

答案 2 :(得分:1)

不确定您要做什么,但是听起来您想通过状态更改来更新A / B / C值。问题在于您是在地图对象之前 render()中定义primaryNode,而不是在render() inside 中定义(总是重新渲染)当状态更改时,请尝试以下操作:

import React, { PureComponent } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';

const Section = item => (
  <>
    <br/>
    <section>
      {item.header}
      <br />
      {item.primaryNode}
      <br />
      {item.bottom}
    </section>
  </>
);

class App extends React.PureComponent {
  constructor(props) {
    super(props);
  }

  state = {
    current: 'B'
  }

  data = ["A", "B", "C"];
  show = [5, 6, 3, 5, 7, 8, 77, 8, 90];

  bottom = () => (
    <select name={"fruit"} value={this.state.current} onChange={this.handleChange}>
      <option value="A">Apple</option>
      <option value="B">Banana</option>
      <option value="C">Cranberry</option>
    </select>
  );

  handleChange = (event) => (
    this.setState({ current: event.target.value })
  );

  primaryNode = () => (
    <div className="primary-node">
      {this.show} ---- {this.state.current}
    </div>
  );

  render() {
    return (
      <>
        State Value - {this.state.current}
        <br/>
        <br/>
        <br/>
        {this.data.map(el => (
          <Section 
            bottom={el === "A" && this.bottom()}
            header={el}
            primaryNode={this.primaryNode()}
          />
        ))}
      </>
    );
  }
}

render(<App />, document.getElementById('root'));

答案 3 :(得分:0)

尝试在map方法内移动render()。 状态更改时会触发render(),因此它是您要寻找的地方