繁体   English   中英

重新渲染 React 组件的单个元素

[英]Re-render single element of an React component

我正在开发一个 TO-DO List React App。 目标是,每次用户单击“添加”按钮时,都会调用saveNote() function 并将新注释添加到notes object 中。然后页面应自动重新呈现, addNote() function被调用并将notes object 中的所有注释作为新的<li>项返回。

现在adNote()只有在我点击Add按钮并开始输入新笔记后才会被调用。为什么?

 function App() { const [note, setNote] = React.useState({ id: "", content: "" }); const [notes, setNotes] = React.useState([]); function createNote(event) { setNote({ id: notes.length + 1, content: event.target.value }); } function saveNote() { console.log(note); setNotes((notes) => [...notes, note]); setNote(""); console.log(notes); } function addNote(note) { return ( <li key={note.id}> <span>{note.content}</span> </li> ); } return ( <div className="container"> <div className="heading"> <h1>To-Do List</h1> </div> <div className="form"> <input onChange={createNote} value={note.content} type="text" /> <button onClick={saveNote} type="submit"> <span>Add</span> </button> </div> <div> <ul> <li>A Item</li> {notes.map(addNote)} </ul> </div> </div> ); } ReactDOM.createRoot(document.body).render(<App />);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

更新

我可以解决我的问题。 关于saveNote() function 的一个问题。如果我调用它,我会得到以下结果:

note = {id: 1, content: "Hello“}
notes = []

为什么notes仍然是空的?

当 React 组件认为可能发生了影响应显示内容的更改时,它们将重新渲染。

这通常是组件的道具(你的没有),或者组件的 state 来自useStateuseReducer (有时是useContext )。

对于您问题中的组件,您的组件“知道”的唯一 state 是note state,对应于您的新注释输入的值。 当您单击“保存注释”时,您更改了notes数组,但 React 不会“知道”这已经发生或者它应该在该数组更改时重新渲染。

当您随后在输入字段中键入时,您使用setNote调用更改了note state,react确实知道,因此它重新呈现,重新调用整个 function,然后使用notes数组中的最新值,所以一切都会更新。 在某种程度上,这是一个巧合。

要解决此问题,您需要将 notes 数组存储在 react state 中,例如:

function App() {
  const [newNote, setNewNote] = React.useState("");
  const [notes, setNotes] = React.useState([]);

  function onNewNoteChanged(event) {
    setNewNote(event.target.value);
  }

  function saveNote() {
    counter++;
    // Append the new note to the old array.
    setNotes((notes)=> [...notes, newNote]);
    setNewNote("");
    console.log(notes);
  }

  function addNote(note) {
    return (
      <li key={note.id}>
        <span>{note.content}</span>
      </li>
    );
  }

  return (
    <div className="container">
      <div className="heading">
        <h1>To-Do List</h1>
      </div>
      <div className="form">
        <input onChange={onNewNoteChanged} value={newNote} type="text" />
        <button onClick={saveNote} type="submit">
          <span>Add</span>
        </button>
      </div>
      <div>
        <ul>
          <li>A Item</li>
          {notes.map(addNote)}
        </ul>
      </div>
    </div>
  );
}

export default App;

你做错了,只对 state 上的重新渲染或道具更改做出反应。 在这种情况下,您的笔记是一个全局列表,而不是 react state,将您的笔记列表更改为 React state,然后在 saveNote() function 上,您可以执行类似的操作。 我们正在传播旧的笔记列表并在列表中附加一个新项目。

另请注意,我正在增加 id,因为反应键应该始终是唯一的,因此反应应该能够跟踪哪个 dom 元素已被更改。

function saveNote() {
    setNotes([...notes, { id: notes.length + 1, content: note }]);
}

在您的示例中,您希望使用 Array of Notes 关联 useState 功能。

首先,让我们看看如何使用 useState() 挂钩来创建数组 state 变量。

import { useState} from "react";

...

const [myArray, setMyArray] = useState([]);

您的数组的初始值将是一个空数组[] 如果不使用从 useState() 返回的方法,则不能直接更新数组。 在我们的例子中,它是setMyArray()

使用 update 方法用一个新数组更新 state,该新数组是使用 JavaScript Spread 运算符将旧数组与新元素组合而成的。

setMyArray(oldArray => [...oldArray, newElement]);

function 将旧数组作为第一个参数希望它的帮助:)

import React from "react";
const notes = [
  {
    id: 1,
    content: "Test"
  }
];

let counter = 1;

function App() {
  const [note, setNote] = React.useState("");
  const [notesState, setNotes] = React.useState(notes);

  function createNote(event) {
    setNote(event.target.value);
  }

  function saveNote() {
    counter++;
    setNotes((nt) =>[...nt , { id: counter, content: note }]);
    console.log(notesState);
  }

  function addNote(note) {
    return (
      <li key={note.id}>
        <span>{note.content}</span>
      </li>
    );
  }

  return (
    <div className="container">
      <div className="heading">
        <h1>To-Do List</h1>
      </div>
      <div className="form">
        <input onChange={createNote} value={note} type="text" />
        <button onClick={saveNote}>
          <span>Add</span>
        </button>
      </div>
      <div>
        <ul>
          <li>A Item</li>
          {notes.map(addNote)}
        </ul>
      </div>
    </div>
  );
}

export default App;

暂无
暂无

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

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