简体   繁体   中英

How to trigger re-render in Parent Component from Child Component

, Using props I was able to effectively pass state upwards from my child component to its parent, but a change in the state does not cause a re-render of the page.

import React, { useState } from "react";

export default function App() {
  const AddToList = (item) => {
    setText([...text, item]);
  };
 const removeFromList = (item) => {
    const index = text.indexOf(item);
    setText(text.splice(index, 1));
  };
  const [text, setText] = React.useState(["default", "default1", "default2"]);
  return (
    <div className="App">
      <div>
        <button
          onClick={() => {
            AddToList("hello");
          }}
        >
          Add
        </button>
      </div>
      {text.map((item) => {
        return <ChildComponent text={item} removeText={removeFromList} />;
      })}
    </div>
  );
}

const ChildComponent = ({ text, removeText }) => {
  return (
    <div>
      <p>{text}</p>
      <button
        onClick={() => {
          removeText(text);
        }}
      >
        Remove
      </button>
    </div>
  );
};

In the snippet, each time AddToList is called, a new child component is created and the page is re-rendered reflecting that. However, when i call removeFromList on the child component, nothing happens. The page stays the same, even though I thought this would reduce the number of childComponents present on the page. This is the problem I'm facing.

Updated Answer (Following Edits To Original Question)

In light of your edits, the problem is that you are mutating and passing the original array in state back into itself-- React sees that it is receiving a reference to the same object, and does not update. Instead, spread text into a new duplicate array, splice the duplicate array, and pass that into setText :

const removeFromList = (item) => {
    const index = text.indexOf(item);
    const dupeArray = [...text];
    dupeArray.splice(index, 1);
    setText(dupeArray);
};

You can see this working in this fiddle

Original Answer

The reason React has things like state hooks is that you leverage them in order to plug into and trigger the React lifecycle. Your problem does not actually have anything to do with a child attempting to update state at a parent. It is that while your AddToList function is properly leveraging React state management:

const AddToList = (item) => {
  setText([...text, item]);
};

Your removeFromList function does not use any state hooks:

const removeFromList = (item) => {
  const index = text.indexOf(item);
  text.splice(index, 1); // you never actually setText...
};

...so React has no idea that state has updated. You should rewrite it as something like:

const removeFromList = (item) => {
  const index = text.indexOf(item);
  const newList = text.splice(index, 1);
  setText(newList);
};

(Also, for what it is worth, you are being a little loose with styles-- your AddToList is all caps using PascalCase while removeFromCase is using camelCase. Typically in JS we reserve PascalCase for class es, and in React we also might leverage it for components and services; we generally would not use it for a method or a variable.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM