React setState 不重新渲染组件

时间:2021-01-24 10:44:34

标签: reactjs react-router components setstate

我得到以下反应代码

const [folders, setFolders] = useState([
    {
        id: 1,
        title: 'name',
        logo: 'logo',
        tasks: 
        [ 
            {
                id: 1,
                text: 'blaas bla bla',
                done: true,
            },
            {
                id: 2,
                text: 'bla bla bla',
                done: false,
            },
        ]
    },
    {
        id: 2,
        title: 'name',
        logo: 'logo',
        tasks: 
        [ 
            {
                id: 3,
                text: 'blasdasda bla bla',
                done: true,
            },
            {
                id: 4,
                text: 'bla bla bla',
                done: false,
            },
        ]
    },
    {
        id: 3,
        title: 'naasdme',
        logo: 'logo',
        tasks: 
        [ 
            {
                id: 5,
                text: 'bla bla bla',
                done: false,
            },
            {
                id: 6,
                text: 'bla bla bla',
                done: false,
            },
        ]
    }
    ]);

function deleteTask( taskId )
{
    setFolders((prev) =>
    {
        prev.forEach( (folder) => 
        {
            folder.tasks = folder.tasks.filter( task => task.id != taskId )
        })
        return prev;
    });
}

代码运行良好,它会更新状态,但不会重新渲染组件。

我将组件与声明式路由一起使用,我尝试了几种方法来检查问题是否出在路由中,但可能不是。

<Route path='/Tasks/:id' render={(props) => 
                    (
                        <Tasks {...props} folders={folders} onDelete={deleteTask} updateTask= {updateTask} />
                    )}
                />
                <Route path='/Tasks/:id' > 
                    <Tasks folders={folders} onDelete={deleteTask} updateTask={updateTask} />
                </Route>

                <Route path='/Tasks/:id' children={<Tasks folders={folders} onDelete={deleteTask} 
 updateTask={updateTask} /> } />

所有这 3 种方法都很好。

组件不重新渲染有什么建议吗?

3 个答案:

答案 0 :(得分:2)

抱歉,我是手机版的。

const deleteTask = (taskId) =>
  setFolders((prev) =>
    prev.map(({ tasks, ...rest }) => ({ ...rest, tasks: tasks.filter((task) => task.id !== taskId) })
  );

答案 1 :(得分:1)

试试这个:

  const deleteTask = (taskId) =>
    setFolders((prev) =>
      prev.map(({ tasks, ...rest }) => ({
        ...rest,
        tasks: tasks.filter((task) => task.id !== taskId),
      }))
    );

工作示例:

const App = () => {
  const [folders, setFolders] = React.useState([
    {
      id: 1,
      title: "name",
      logo: "logo",
      tasks: [
        {
          id: 1,
          text: "blaas bla bla",
          done: true,
        },
        {
          id: 2,
          text: "bla bla bla",
          done: false,
        },
      ],
    },
    {
      id: 2,
      title: "name",
      logo: "logo",
      tasks: [
        {
          id: 3,
          text: "blasdasda bla bla",
          done: true,
        },
        {
          id: 4,
          text: "bla bla bla",
          done: false,
        },
      ],
    },
    {
      id: 3,
      title: "naasdme",
      logo: "logo",
      tasks: [
        {
          id: 5,
          text: "bla bla bla",
          done: false,
        },
        {
          id: 6,
          text: "bla bla bla",
          done: false,
        },
      ],
    },
  ]);

  const deleteTask = (taskId) =>
    setFolders((prev) =>
      prev.map(({ tasks, ...rest }) => ({
        ...rest,
        tasks: tasks.filter((task) => task.id !== taskId),
      }))
    );

  return folders.map((folder) => (
    <div>
      <h1>{folder.title}</h1>
      {folder.tasks.map((task) => (
        <div>
          <p>{task.text}</p>
          <button onClick={() => deleteTask(task.id)}>Delete</button>
        </div>
      ))}
    </div>
  ));
};
ReactDOM.render(<App />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

答案 2 :(得分:0)

您应该使用 map 而不是 forEach 因为 map 返回一个新数组。组件不会重新渲染,因为您修改了数组 folders,但您没有更改引用。 React 不认为状态改变了,因为它读取的值(数组的引用«它在内存中的起点»)没有改变。