简体   繁体   English

如何在 reactJS 的拼接方法后重新渲染页面?

[英]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. onClick方法拼接数组后,数据似乎删除了,但页面没有更新。 How to reRender or update the page to reflect the changes?如何重新呈现或更新页面以反映更改?

Home.js:主页.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.我尝试使用react-router-domhistory中的useNavigate ,但它没有用。

Maybe you can utilize state for this, can use useState hooks也许你可以为此利用状态,可以使用useState钩子

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;

In React functional components you can use a hook called useState.在 React 函数式组件中,您可以使用一个名为 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.然而,改变状态在 React 生态系统中是一个很大的禁忌,因为它大量实践了不变性的概念。 Splice mutates the state by deleting or adding to the element itself. Splice 通过删除或添加元素本身来改变状态。

Instead of mapping and splicing you can use filter with the setter.除了映射和拼接之外,您还可以将过滤器与设置器一起使用。 Filter is immutable, because it creates a shallow copy. Filter 是不可变的,因为它创建了一个浅拷贝。 You want to create a shallow copy, but without the item that has the id given as a parameter in your function.您想要创建一个浅表副本,但没有在您的函数中将 id 作为参数给出的项目。 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.现在您所要做的就是映射状态“数据”而不是直接映射 homeData。

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.在当前的实现中,代码正在改变一个属于任何 React 状态的对象,因此 React 不知道需要重新渲染任何东西。

Things to keep in mind:要记住的事情:

  1. Array.prototype.splice does an in-place mutation of the array it operates over. Array.prototype.splice对其操作的数组进行就地突变。

    The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place . splice()方法通过删除或替换现有元素和/或就地添加新元素来更改数组的内容。 To access part of an array without modifying it, see slice() .要访问数组的一部分而不修改它,请参阅slice()

  2. React components rerender for one of three reasons: React 组件由于以下三个原因之一而重新渲染:

    1. A local component state update is enqueued, component and sub-ReactTree rerender本地组件状态更新入队,组件和子 ReactTree 重新渲染
    2. A passed props value is updated, component and sub-ReactTree rerender传递的 props 值被更新,组件和子 ReactTree 重新渲染
    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.要正确渲染更新HomeData数组,它必须是 React 组件状态的一部分。 When updating React state, all state, and sub-state, necessarily needs to be a new object reference.在更新 React state 时,所有的 state,和 sub-state,必然需要一个的对象引用。 This is because React uses a shallow reference equality check.这是因为 React 使用浅层引用相等性检查。 It's far more common to use Array.prototype.filter to filter an existing array and return a new array reference.使用Array.prototype.filter过滤现有数组返回的数组引用更为常见。

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;

You should use the useState hooks to update the view您应该使用 useState 挂钩来更新视图

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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