【问题标题】:Why is my empty object in useState hook rendering?为什么我的空对象在 useState 钩子渲染中?
【发布时间】:2022-01-01 18:48:11
【问题描述】:

我只是在功能组件和反应状态挂钩上刷新自己,构建一个简单的反应待办事项列表应用程序 - 所有简单的功能都已构建,但在初始状态下我有一个错误,其中有一个空任务渲染列表。我错过了什么?任何帮助将不胜感激。 :)

App.js:

import TodoList from './TodoList'

function App() {
  return (
    <div>

      <TodoList /> 

    </div>
  );
}

export default App;


Todolist.js:

import React, {useState} from 'react'
import NewTodoForm from './NewTodoForm'
import Todo from './Todo'

const TodoList = () => {
    const [state, setState] = useState({
      list: [{title: "", id: ""}]
    })

    const addTodo = (newTodo) => {
        setState({ 
            list: [...state.list, newTodo]
         })
         console.log('after state change in addtodo', state.list.title)

    }

    const remove = (toDoId) => {
        console.log('logging remove')
        setState({
            list: state.list.filter(todo => todo.id !== toDoId)
        })
    }

    const strike = e => {
            const element = e.target;
            element.classList.toggle("strike");
    } 

    const update = (id, updatedTask) => {
        //i cant mutate state directly so i need to make a new array and set that new array in the state
        const updatedTodos = state.list.map(todo => {
            if (todo.id === id) { // find the relevant task first by mapping through existing in state and add updated info before storing it in updatedtodos
                return { ...todo, title: updatedTask}
            }
                return todo
        })
        console.log('updated todos', updatedTodos)
        setState({
            list: updatedTodos
        })
        console.log('list after updating state')
    }
    return (
        <div className="TodoList">
            <h1>Todo List<span>A simple react app</span></h1>
                <NewTodoForm addingTodo={addTodo}/> 

            { state.list.map(todo => <Todo id={todo.id} key={todo.id} title={todo.title} updateTodo={update} strikeThrough={strike} removeTodo={() => remove(todo.id)} />) }
           
          
        </div>
    )
}

export default TodoList


Todo.js:

import React, {useState} from 'react'

const Todo = ({id, title, removeTodo, strikeThrough, updateTodo}) => {
    const [state, setState] = useState({
        isEditing: false,
    })

    const [task, setTask] = useState(title);



    const handleUpdate = (e) => {
        e.preventDefault()
        updateTodo(id, task)
        setState({ isEditing: false})
    }

    const updateChange = (e) => {
    //    setState({...state, [e.target.name]: e.target.value})
       setTask(e.target.value)
       console.log(task)

    }

    return (
        <div>
            {state.isEditing ? 
            <div className="Todo">
                <form className="Todo-edit-form" onSubmit={handleUpdate}>
                    <input
                        type="text"
                        value={task}
                        name="task"
                        onChange={updateChange}
                    >
                    </input>
                    <button>Submit edit</button>
                </form>
            </div> : 
            <div className="Todo">
                <ul>
                <li className="Todo-task" onClick={strikeThrough}>{title}</li>
            </ul>
            <div className="Todo-buttons">
            <button onClick={() => setState({isEditing: !state.isEditing})}><i class='fas fa-pen' /></button>
            <button onClick={removeTodo}><i class='fas fa-trash' /></button>
            </div>
            </div>
                }
           
        </div>
    )
}

export default Todo

【问题讨论】:

  • 因为您从列表list: [{title: "", id: ""}] 中的一个空任务开始,虽然这是意料之中的,所以您可以输入一个新的待办事项,不是吗?还是我误解了你的问题?
  • 嗨@Dominic,感谢您的回复。在设置状态之前,我需要先将状态初始化为空字符串,所以我不确定这是问题所在..
  • 您的意思是您需要在初始渲染中渲染空任务,当添加了任务时您想删除空任务?
  • 嗨@SaeedShamloo,不完全是。我根本不希望空对象渲染/显示..我之前从未遇到过这个问题,哈哈
  • 为什么不用空数组初始化列表,像这样:list: []

标签: javascript reactjs react-hooks


【解决方案1】:

你正在渲染你的待办事项:

{ state.list.map(todo => <Todo id={todo.id} key={todo.id} title={todo.title} updateTodo={update} strikeThrough={strike} removeTodo={() => remove(todo.id)} />) }

你的初始状态是:

{ list: [{title: "", id: ""}] }

上述状态会导致 React 为你渲染一个空的待办事项。清除阵列后,您应该看不到任何东西。另一种选择是更改您的渲染并添加一个检查待办事项值是否为空的条件,以不渲染它们。

【讨论】:

  • 嗨@akds,感谢您的建议。我想我可能必须这样做并在地图中添加todo.title === '' ? '' : 以进行渲染...所以它不再渲染但我仍然想知道为什么一个空对象仍然在反应状态钩子中渲染-感谢您的观察.
  • 数组为空 => 不渲染,数组包含项目 => 发生渲染。如果数组中的项目缺少字段,即“不适合”,react 将引发错误,但只要代码适合(并且它确实具有值,在您的情况下为空字符串),它将被渲染。
【解决方案2】:

TodoList 中的初始状态似乎是 list:[{title: "", id: ""}],其中包含空的 title 和 id。由于它被映射为创建 Todo,我认为它以一个空的 Todo 开头。

【讨论】:

    猜你喜欢
    • 2022-01-24
    • 2022-08-16
    • 1970-01-01
    • 2021-10-31
    • 1970-01-01
    • 2020-10-22
    • 2020-07-11
    • 2022-01-25
    相关资源
    最近更新 更多