2

我有一个包含问题字段的 div 列表。对于每个按钮单击,我都会添加一行新的问题字段,并在状态中记住整个列表以及有多少行。我尝试添加一个删除按钮,但是当我的删除功能时,状态变量的值似乎是从创建行时记住的。我该如何解决这个问题,以便我可以访问 HandleDelete 函数中的完整列表?

const OefeningAanvragenDagboek = () => {
const { t, i18n } = useTranslation()
const [questionCount, setQuestionCount] = useState(1)
const [questionList, setQuestionList] = useState([])

const createNewLine = () =>{
    var newLine=
        <div>
            <Field type="text" name={"vraag" + questionCount}/>
            <Field component="select" name={"antwoordMogelijkheid"+questionCount}>
                <option value="">...</option>
                <option value="open">{t('oefeningAanvragenDagboek.open')}</option>
                <option value="schaal">{t('oefeningAanvragenDagboek.scale')}</option>
            </Field>
            <Field type="text" name={"type"+questionCount}/>
            <button onClick={() => HandleDelete(questionCount-1)}>{t('assignmentCard.delete')}</button>
        </div>

      setQuestionList(questionList => [...questionList, newLine])
      setQuestionCount(questionCount+1)
  }

  const HandleDelete = (index)=> {
      console.log(questionList)
      // setQuestionList(questionList.splice(index, 1))

  }

  return (
      <div>
          <button onClick={createNewLine}>{t('oefeningAanvragenDagboek.addQuestion')}</button>
          {questionList}
      </div>
  )
}
4

3 回答 3

1

您可以将事件处理程序从容器传递给子项,然后从客户端调用事件处理程序。

例如,假设我有一个显示项目列表的应用程序,每个项目都有一个删除按钮,可以将它们从列表中删除。在这种情况下,父组件将向子组件提供项目列表事件处理程序,然后子组件将负责渲染调用事件处理程序

看看我粘贴以下代码的这个代码框:

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

export function List(props) {
  return (
    <div>
      {props.items.map((i, idx) => (
        <div class="item" key={idx}>
          {i} <span onClick={() => props.onDelete(idx)}>X</span>
        </div>
      ))}
    </div>
  );
}

export default function App() {
  const [items, setItems] = useState([
    "Item 1",
    "Item 2",
    "Item 3",
    "Item 4",
    "Item 5",
    "Item 6"
  ]);

  const deleteItem = (index) => {
    if (index >= 0 && index < items.length) {
      const newItems = items.slice();
      newItems.splice(index, 1);
      setItems(newItems);
    }
  };

  return (
    <div className="App">
      <List items={items} onDelete={deleteItem}></List>
    </div>
  );
}

于 2020-10-06T03:07:48.887 回答
1

使用功能setStateHandleDelete关闭questionList

setQuestionList(questionList => questionList.splice(index, 1))

updater 函数接收到的 state 和 props 都保证是最新的。

于 2020-03-12T16:55:20.950 回答
1

在撰写本文时,主要解决了OP 评论部分的问题,除了问题之外,该部分还获得了赏金。

有问题的沙盒:https ://codesandbox.io/s/charming-architecture-9kp71?file=/src/App.js

基本上解决这个问题的方法就是对回调函数的参数进行所有的操作。在我上面链接的沙盒问题的情况下,如果您查看removeToast下面的代码,则操作正在list数组上完成。

有问题的代码:

export default function App() {
  const [list, setList] = useState([]);

  const removeToast = (id) => {
    const newList = list.filter(({ toastId }) => toastId !== id);
    setList([...newList]);
  };

  const addToast = () => {
    const toastId = Math.random().toString(36).substr(2, 9);
    const newList = [
      ...list,
      {
        toastId,
        content: (
          <>
            <button onClick={() => removeToast(toastId)}>Hi there</button>
            Hello {toastId}
          </>
        )
      }
    ];
    setList([...newList]);
  };

  return (
    <>
      <button onClick={addToast}>Show Toast</button>
      <Toaster removeToast={removeToast} toastList={list} />
    </>
  );
}

然而,由于removeToast在 上有一个闭包list,我们需要对先前的状态进行过滤,这又可以通过 setState 回调的第一个参数访问

修复:

const removeToast = (id) => {
  setList((prev) => {
    return prev.filter(({ toastId }) => toastId !== id);
  });
};

解决方案:https ://codesandbox.io/s/suspicious-silence-r1n41?file=/src/App.js

于 2020-10-06T01:55:55.460 回答