简体   繁体   English

React 中的强制组件渲染

[英]Force Component Rerender in React

I have a react app that fetches a list of todos from the backend, displays them in a list, and offers you a button to add a new one.我有一个 react 应用程序,它从后端获取待办事项列表,将它们显示在列表中,并为您提供一个添加新待办事项的按钮。

I notice that the newly added to do will only appear in the list AFTER I refresh the page (eg after it fetches from the backend).我注意到新添加的待办事项只会在我刷新页面后出现在列表中(例如,在它从后端获取之后)。 I'd like to force the component to re-render with the newly added to do, ideally without a backend call.我想强制组件重新渲染新添加的任务,理想情况下没有后端调用。 How can I do that?我怎样才能做到这一点?

Component AFTER I've hit "add" - text stays in the box, does not appear in the list我点击“添加”后的组件 - 文本留在框中,未出现在列表中在此处输入图像描述

Page AFTER I've hit add and refreshed the page - appears below - I'd like this behavior to happen without a manual refresh在我点击添加并刷新页面之后的页面 - 出现在下方 - 我希望这种行为在没有手动刷新的情况下发生在此处输入图像描述

App.tsx应用程序.tsx

    import React, {useState, useEffect} from "react"
import './App.css';
import APIHelper from "./APIHelper";

function App() {
  const [todos, setTodos] = useState([])
  const [todo, setTodo] = useState("")

  useEffect(() => {
    const fetchTodoAndSetTodos = async () => {
      const todos = await APIHelper.getAllTodos()
      setTodos(todos)
    }
    fetchTodoAndSetTodos()
  }, [])

  const createTodo = async (e: { preventDefault: () => void; }) => {
    e.preventDefault()
    const newTodo = await APIHelper.createTodo(todo)
    // @ts-ignore
    setTodos([...todos, newTodo])
  }

  return (
          <div className="App">
            <div>
              <input
                      id="todo-input"
                      type="text"
                      value={todo}
                      onChange={({target}) => setTodo(target.value)}
              />
              <button type="button" onClick={createTodo}>
                Add
              </button>
            </div>
            <ul>
              {todos.map(({_id, task, completed}, i) => (
                      <li
                              key={i}
                              className={completed ? "completed" : ""}
                      > {task}
                      </li>
              ))}
            </ul>
          </div>
  )
}

export default App

APIHelper.js APIHelper.js

import axios from "axios"

const API_URL_GET = "http://localhost:8080/"
const API_URL_CREATE = "http://localhost:8080/create"

async function createTodo(task) {
    const { data: newTodo } = await axios.post(API_URL_CREATE, {
        task,
    })
    return newTodo
}

async function getAllTodos() {
    const { data: todos } = await axios.get(API_URL_GET)
    return todos
}
export default { createTodo, getAllTodos }



  [1]: https://i.stack.imgur.com/CuYUK.png
  [2]: https://i.stack.imgur.com/PDne4.png

Inside the createTodo function, you'll need to reset your todo state.createTodo function 中,您需要重置您的todo state。 Which means setting it to an empty string again:这意味着再次将其设置为空字符串:

const createTodo = async (e: { preventDefault: () => void; }) => {
    // ...
    setTodo(''); // Here
}

For me it seems like that APIHelper.createTodo returns a wrong object.对我来说, APIHelper.createTodo似乎返回了错误的 object。 The list item is at the screen, but has no task property.列表项在屏幕上,但没有task属性。
As mentioned above, Try to prevent forceUpdate() the component.如上所述,尽量防止 forceUpdate() 组件。

async function createTodo(task) {
    const { data: newTodo } = await axios.post(API_URL_CREATE, {
        task,
    });
    // check this newTodo value
    return newTodo
}

To reset the input field, setTodo("") to an empty string要重置input字段, setTodo("")设置为空字符串

Normally you should avoid this but still here you go you can using forceUpdate通常你应该避免这种情况,但你仍然在这里 go 你可以使用 forceUpdate

In your component, you can call this.forceUpdate() to force a rerender.在您的组件中,您可以调用this.forceUpdate()来强制重新渲染。

Documentation: https://facebook.github.io/react/docs/component-api.html文档: https://facebook.github.io/react/docs/component-api.html

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

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