techie_questie
techie_questie

Reputation: 1522

How to update the current state with current and previous state with react hooks

In my react application, I have a Parent and Child component. In my parent component, i am including filters from Child component. Whatever values i select from filter, I am passing that to my api request param which is called under handleFilterChange method in my ParentComponent.But, i am noticing that if i select one filter from ChildComponent, it gets passed properly but on selecting two filters, it's always the latest selected filter value that gets passed. So, i think, i somehow need to save my previous state in handleFilterChange method but not sure how to achieve it. Here is my code snippet.

ParentComponent.js-

const ParentComponent = props => {
  const [filterObj, setFilterObj] = useState({});

  const handleFilterChange = filters => {
    console.log(filters); // Show only latest selected filter
    setFilterObj(filterObj);
    //API call which will pass filters in request params
  };

  return (
    <ChildComponent onChange={handleFilterChange} />
  );
}

ChildComponent.js

const ChildComponent = props => {

  const handleChange = value => {
    console.log(values);// Shows all of the selected filters
    onChange({
      ...Object.keys(values).reduce((val, key) => (isEmpty(value[key]) ? val : { [key]: value[key] }), {}),
    });
  };

  return (
    <Filter onFilterChange={handleChange} />
  );
}

For Example, i have Filter A and Filter B. First time, when i select Filter A, i see parameter values has Filter A and same gets passed to my ParentComponent. But, when i select Filter B after having Filter A selected, it only passes Filter B(latest selected value) to my ParentComponent in handleFilterChange method. So, the filter parameter in handleFilterChange method will only have one object i.e Filter B. I am expecting it to have Filter A and Filter B. When selecting filters individually, my code works fine but only when i try to select both filters, it does not work. Any suggestion here would really help. Please note, the parameters, filters and values are objects.

Upvotes: 1

Views: 1096

Answers (3)

Md. Abu Sayed
Md. Abu Sayed

Reputation: 2486

In ReactJs component allowance re-render the component when the component state are changed. So, when you change the filter from parent component you just update the state previous state ReactJs child component automatically re-render called.

Example this link here codesendbox.io or above this code:

Parent component

import React, {useState} from "react";
import "./styles.css";
import Children from "./Children";

export default function App() {

  const [filter, setFilter] = useState('A');

  const handleChange = e => setFilter(e.target.value);

  return (
    <>
      Filter:{" "}
      <select onChange={(e)=>handleChange(e)}>
        <option value="A">A</option>
        <option value="B">B</option>
        <option value="C">C</option>
      </select>
      <Children filter={filter} />
    </>
  );
}

Children component

import React from "react";

const Children = props => {
  return <h1>Children filder is : {props.filter}</h1>;
};
export default Children;

Finally, the output is:

enter image description here

Note: This answer is only for clear concept parent and chield in ReactJS

==== Thanks ====

Upvotes: 0

Prabesh Gautam
Prabesh Gautam

Reputation: 11

You can use useState() hook for updating the current state based on the previous state.

const [state, setState] = React.useState(default) 

It take in the default value for your state.

React.useState() returns an array where the first value is the variable to store value for the state and second is the function which helps to update the value.

You can simply call the function passing the new value to it to update the state value.

Upvotes: 0

Shubham Khatri
Shubham Khatri

Reputation: 281626

In your child's handleChange function you have't passed on the entire set of filters to parent onChange.

Inside reduce you are overwriting the filters object always instead you need to merge the values

Updated code

const handleChange = value => {
    console.log(values);// Shows all of the selected filters
    onChange({
      ...Object.keys(values).reduce((val, key) => (isEmpty(value[key]) ? val : { ...val, [key]: value[key] }), {}),
    });
  };

Upvotes: 1

Related Questions