score:1

Accepted answer

The class field map is initialized only once, at first component render. It does not really matter that you change the state, that variable holds the very same data and does not change in time.

One of the solutions would be moving that variable into 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>)
}

or you could transform map field into a method:

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>)
}

So the data returned by map is always up-to-date.

score:0

Try moving the map inside the render() method. render() is fired when the state changes so it's the place You're looking for

score:1

I think you're making this more confusing than it needs to be by holding all these values as class properties. The reason that they are not updating is because this.map is only defined once. You don't need map at all, just render your nodes directly inside render function which gets called on state changes:

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>
  )
}

And if you really want it to be a map, then define it inside 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>
}

score:1

Not entirely sure what you're wanting to do, but it sounds like you want your A/B/C values to be updated with state-change. The problem is that you are defining the primaryNode in your map-object before render(), rather than inside of render() (which always re-renders when state changes. Try this:

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'));

Related Query

More Query from same tag