0
votes

i have the following problem: I have parent component (where is button, and array of child components to render).

To each child i pass props and child uses it as state, then changes it. The problem is that children doesn't rerender.

As it may seem not understandable, here is something more clear (i hope):

Here is the simplified version of child.js

export default function ChildComponent(props) {
  const [open, setOpen] = React.useState(props.open);

  const handleClick = () => {
    setOpen(true);
  }; /* i actually never use handleClick */

  const handleClose = (event) => {
    setOpen(open => !open);
  };

  return (
    <div>
        <SomeComponent hideAfterTimeMs={1000} onClose={handleClose}/>
    </div>
  );
}

Parent:

import React from "react";
import Child from "./demo";

class MyClass extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      something: false,
    };
  }

  displayKids = () => {
    const a = [];
    for (let i = 0; i < 1; i++) {
      a.push(<Child open={true} key={i} message={"Abcd " + i} />);
    }
    return a; 
  };

  handleChange = e => {
    this.setState(prevState => ({
      something: !prevState.something,
    }));
  };

  render() {
    return (
      <div>
        <button onClick={this.handleChange}>Nacisnij mnie</button>
        {this.displayKids()}
      </div>
    );
  }
}
export default MyClass;

So basically the child component renders, and sets its "open" to false, and when i click button again i hoped for displaying child again, but nothing happens.

Child renders something that disappears after a few seconds.

2
That is what your code does, so seems expected. Can you be more specific about what isn't working? What button is being clicked? So after the child auto hides after a timeout, what is supposed to re-open it? - Drew Reese
Yeah, sure. Basically i want to render the same component many times (where the components disappears after specific amount time, that's why when i click i want it to render again). To be more specific I click button in parent component (there is only one there) and then i want to display children with displayKids method. The button changes some state so i thought this will cause rerender but its not working that way. - emsiiggy
What child component does is when "open" is "true" then something (like some text) is displayed, and after specific amount of time(like 1000ms) handleClose is called and "open" is changed to "false". So from parent i pass the variable open={true} and childs uses this for initial state (from props) - emsiiggy
Please provide a working snippet. - Dhaval Jardosh

2 Answers

1
votes

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity.

You are using the index as a key. Please try to use a unique key. E.g. child id or random hash code.

If the key is unique and new it will re-render. Right now it is not re-rendering because the key is the same.

Check out: https://reactjs.org/docs/lists-and-keys.html#keys

0
votes

It doesn't look like your components are linked in any meaningful way. Clicking the button on the My Class component updates the something state, but that state is not passed to the Child component.

Similarly, the SomeComponent component handles its own close, and tells the Child component it is closed via handleClose - but that is not communicated to the parent and neither does the parent or Child communicate any open state to SomeComponent.

Changing some state on Child will not rerender it's own children. Something new has to be passed as a prop for that to happen.