简体   繁体   English

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

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

I am working on a TO-DO List React App.我正在开发一个 TO-DO List React App。 The goal is, that every time the user clicks on the "Add" button the saveNote() function gets called and a new note is added to the notes object. Then the page should automatically re-render and by that the addNote() function gets called and returns all notes within notes object as a new <li> item.目标是,每次用户单击“添加”按钮时,都会调用saveNote() function 并将新注释添加到notes object 中。然后页面应自动重新呈现, addNote() function被调用并将notes object 中的所有注释作为新的<li>项返回。

Right now adNote() only gets called after I clicked on the Add button and start entering a new note.. why?现在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>

UPDATE更新

I could fix my problem.我可以解决我的问题。 Just one question regarding the saveNote() function. If I call it, I get the following result:关于saveNote() function 的一个问题。如果我调用它,我会得到以下结果:

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

Why is notes still empty?为什么notes仍然是空的?

React components will re-render when they think that something may have changed that affects what should be displayed.当 React 组件认为可能发生了影响应显示内容的更改时,它们将重新渲染。

This is normally either the component's props (yours doesn't have any), or the component's state from useState or useReducer (and sometimes useContext ).这通常是组件的道具(你的没有),或者组件的 state 来自useStateuseReducer (有时是useContext )。

For the component in your question, the only state your component "knows about" is the note state, corresponding to the value of your new note input.对于您问题中的组件,您的组件“知道”的唯一 state 是note state,对应于您的新注释输入的值。 When you click "Save note", you change the notes array, but react doesn't "know" that this has happened or that it should re-render when that array changes.当您单击“保存注释”时,您更改了notes数组,但 React 不会“知道”这已经发生或者它应该在该数组更改时重新渲染。

When you subsequently type in the input field, you change the note state with the setNote call, which react does know about, and so it re-renders, re-calling the entire function, which then uses the latest values from the notes array, so everything updates.当您随后在输入字段中键入时,您使用setNote调用更改了note state,react确实知道,因此它重新呈现,重新调用整个 function,然后使用notes数组中的最新值,所以一切都会更新。 In a way, this is being fixed by a coincidence.在某种程度上,这是一个巧合。

To fix the issue, you need to store the notes array in a react state, for example:要解决此问题,您需要将 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;

you are doing it wrong, react only re-renders on state or prop change.你做错了,只对 state 上的重新渲染或道具更改做出反应。 in this case your notes is a global list not a react state, change your notes list to React state and then on saveNote() function you can do something like this.在这种情况下,您的笔记是一个全局列表,而不是 react state,将您的笔记列表更改为 React state,然后在 saveNote() function 上,您可以执行类似的操作。 we are spreading the old notes list and appending a new item in the list.我们正在传播旧的笔记列表并在列表中附加一个新项目。

also note I am making increment on id as react keys should always be unique so react should be able to track which dom element has been changed.另请注意,我正在增加 id,因为反应键应该始终是唯一的,因此反应应该能够跟踪哪个 dom 元素已被更改。

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

In your example, you'd like to associate the useState capability using Array of Notes.在您的示例中,您希望使用 Array of Notes 关联 useState 功能。

First, let's see how to use the useState() hook for creating an array state variable.首先,让我们看看如何使用 useState() 挂钩来创建数组 state 变量。

import { useState} from "react";

...

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

The initial value of your array would be an empty array [] .您的数组的初始值将是一个空数组[] You can't update the array directly without using the method returned from useState().如果不使用从 useState() 返回的方法,则不能直接更新数组。 In our case, it's setMyArray() .在我们的例子中,它是setMyArray()

Use the update method to update the state with a new array that's created by combining the old array with the new element using JavaScript Spread operator.使用 update 方法用一个新数组更新 state,该新数组是使用 JavaScript Spread 运算符将旧数组与新元素组合而成的。

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

The function will have the old array as a first parameter Hope its help:) 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