Dharmesh
Dharmesh

Reputation: 23

How to reRender the Page after Splice Method in reactJS?

After onClick method to splice array, data seems to delete but page isn't updating. How to reRender or update the page to reflect the changes?

Home.js:

import React from "react";
import "./HomeStyles.css";
import HomeData from "./HomeData";

function Home() {
    function handleDelete(id) {
        var index = HomeData.map(function (e) {
            return e.id;
        }).indexOf(id);
        HomeData.splice(index, 1);
    }

    return (
        <>
            <section className="home_section">
                <div className="home_container">
                    {HomeData.map((item) => {
                        return (
                            <div className="Heading_container" key={item.id}>
                                <h1 className="home_heading">{item.heading}    </h1>
                                <button onClick={handleDelete}>Delete</button>
                            </div>
                        );
                    })}
                    
                    <button className="submit_btn">Submit</button>
                </div>
            </section>
        </>
    );
}

export default Home;

Data:

const HomeData = [
    {
        id: 1,
        heading: 'This is first Heading'
    },
    {
        id: 2,
        heading: 'This is Second Heading'
    },
]

export default HomeData;

I have tried using useNavigate from react-router-dom and history, but it didn't work.

Upvotes: 1

Views: 617

Answers (4)

Jason Thenneil
Jason Thenneil

Reputation: 11

Maybe you can utilize state for this, can use useState hooks

It will be something like this:

import React, {useState} from "react";
import "./HomeStyles.css";
import HomeData from "./HomeData";

function Home() {

    const [data,setData] = useState(HomeData)
    function handleDelete(id) {
        const newData = data.filter((e) => e.id !== id)
        setData(newData)
    }

    return (
        <>
            <section className="home_section">
                <div className="home_container">
[don't forget to use the state here] >>> {data.map((item) => {
                        return (
                            <div className="Heading_container" key={item.id}>
                                <h1 className="home_heading">{item.heading}    </h1>
                                <button onClick={handleDelete}>Delete</button>
                            </div>
                        );
                    })}
                    
                    <button className="submit_btn">Submit</button>
                </div>
            </section>
        </>
    );
}

export default Home;

Upvotes: 1

Yoosef Palamadathil
Yoosef Palamadathil

Reputation: 79

You should use the useState hooks to update the view

import React, { useState } from "react"; //imported useState
import "./HomeStyles.css";
import HomeData from "./HomeData";

function Home() {
 const [homeData, setHomeData] = useState(HomeData); //Added here

 function handleDelete(id) {
    const newData = homeData.filter((e) => e.id !== id)
    setHomeData(newData)
}

return (
    <>
        <section className="home_section">
            <div className="home_container">
                {homeData.map((item) => { //changed state here
                    return (
                        <div className="Heading_container" key={item.id}>
                            <h1 className="home_heading">{item.heading}    </h1>
                            <button onClick={handleDelete}>Delete</button>
                        </div>
                    );
                })}
                
                <button className="submit_btn">Submit</button>
            </div>
        </section>
    </>
);
}

export default Home;

Upvotes: -1

Drew Reese
Drew Reese

Reputation: 203099

Issue

In the current implementation the code is mutating an object that ins't part of any React state, so React isn't aware that anything needs to be rerendered.

Things to keep in mind:

  1. Array.prototype.splice does an in-place mutation of the array it operates over.

    The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place. To access part of an array without modifying it, see slice().

  2. React components rerender for one of three reasons:

    1. A local component state update is enqueued, component and sub-ReactTree rerender
    2. A passed props value is updated, component and sub-ReactTree rerender
    3. The parent component rerendered (because state and/or props updated)

Solution

To correctly render and update the HomeData array it necessarily should be part of a React component state. When updating React state, all state, and sub-state, necessarily needs to be a new object reference. This is because React uses a shallow reference equality check. It's far more common to use Array.prototype.filter to filter an existing array and return a new array reference.

Home Example:

import React from "react";
import "./HomeStyles.css";
import HomeData from "./HomeData";

function Home() {
  const [homeData, setHomeData] = React.useState(HomeData); // <-- initialize state

  const handleDelete = (id) => {
    setHomeData(data => data.filter(el => el.id !== id)); // <-- filter and return new array
  };

  return (
    <section className="home_section">
      <div className="home_container">
        {homeData.map((item) => ( // <-- map homeData state
          <div className="Heading_container" key={item.id}>
            <h1 className="home_heading">{item.heading}</h1>
            <button
              button="button" // <-- should be explicit with button type
              onClick={handleDelete}
            >
              Delete
            </button>
          </div>
        ))}
                    
        <button
          className="submit_btn"
          type="submit" // <-- should be explicit with button type
        >
          Submit
        </button>
      </div>
    </section>
  );
}

export default Home;

Upvotes: 0

Donphin
Donphin

Reputation: 31

In React functional components you can use a hook called useState. With this hook you can get and set the data however you want it.

const [data, setData] = useState(homeData);

Mutating state however is a big no-no in the React ecosystem because of the fact that it heavily practices the concept of immutability. Splice mutates the state by deleting or adding to the element itself.

Instead of mapping and splicing you can use filter with the setter. Filter is immutable, because it creates a shallow copy. You want to create a shallow copy, but without the item that has the id given as a parameter in your function. This would translate to the following code:

setData(homeData.filter(home => home.id !== id));

Now all you have to do is map through the state "data" instead of the homeData directly.

Upvotes: 1

Related Questions