简体   繁体   中英

Lifting state from child component to parent

I have 2 child components: a Categories select and a Search input text and submit button. They both have their own state. I have to use those two components in a parent page. I need to know in which category I have to do the search and to achieve this I think I should lift the state, so that the parent will handle it.

Basically I removed state from the child component and placed it on the parent, ending up with something like this (simplified code):

export default ParentPage = () => {

  const [searchString, setSearchString] = useState("");
  const [category, setCategory] = useState(0);

  const onSearch = () => {
    // search for searchString in the selected category
  }

  return (
    <>
      <Categories category={category} setCategory={setCategory} />
      <Search searchString={searchString} setSearchString={setSearchString} onSearch={onSearch} />
    </>
  )
}

Is this a good approach? It seems a bit verbose, is there a more compact way to pass the state and setState to child components?

In place of this:

<Categories category={category} setCategory={setCategory} />
<Search searchString={searchString} setSearchString={setSearchString} />

You can also use the below one, as you are keeping same name props as states:

<Categories {...{ category , setCategory }} />
<Search {...{ searchString , setSearchString }} />

Note: But I can't see any purpose of lifting state up, from the provided code, so can't say anything about it.


After the code update, you can do it something like this:

export default ParentPage = () => {

  const [searchString, setSearchString] = useState("");
  const [category, setCategory] = useState(0);

  const onSearch = () => {
    // search for searchString in the selected category

    // if you are filtering category and calling setCategory, then it's all good
    // else you need to pass `searchString` in `Categories` to filter the data

  }

  return (
    <>
      <Categories {...{category , setCategory }} />
      <Search {...{searchString , setSearchString , onSearch}} />
    </>
  )
}

Hi I have prepared a complete example here. You need to pass child state from child to parent using callback and then you receive child's state on parent and send that state to another child.

Parent Component

import React, {useEffect, useState} from 'react';
import Child from "./Child";
import Sibling from "../Sibling";

function CParent(props) {

    const [status, setStatus] = useState(false);

    function setOpeningValue(status) {
        console.log('From Child to Parent:' + status);
        setStatus(status);
    }
    return (
        <div>
            <Child setOpeningValue={setOpeningValue}/>
            <Sibling status={status}/>
        </div>
    );
}
export default CParent;

Child Component

import React, {useEffect, useState} from 'react';

// Child to Parent communication
function Child(props) {
    const {setOpeningValue} = props;
    const [isOpen, setOpen] = useState(false);

    function clickHandler() {
        setOpen(!isOpen);
        setOpeningValue(`changes is ${!isOpen}`);
    }
    return (
        <div>
            <button onClick={clickHandler}>Open</button>
        </div>
    );
}
export default Child;

Sibling Component

import React, {useEffect, useState} from 'react';

function Sibling(props) {
    const {status} = props;
    const [isOpen, setOpen] = useState(false);

    return (
        <div>
            From Child to Parent to Another Child (Sibling) {status}
        </div>
    );
}
export default Sibling;

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