【问题标题】:How can I create an instance of an Object in React..?如何在 React.. 中创建对象的实例?
【发布时间】:2021-11-23 22:17:32
【问题描述】:

我对 react 和 javascript 非常陌生,但我正在尝试构建一个简单的 ToDo 应用程序。在我想从文件中读取数据并在屏幕上显示该数据之前,这并不复杂。问题是我不知道如何创建一个新的 Todo 对象以将其作为参数传递给 addTodo 函数。谢谢大家,希望你们能帮助我!!

这里放代码(请看-loadFromFile-函数,有问题的地方:

import React, { useState } from 'react';
import TodoForm from './TodoForm';
import Todo from './Todo';
import data from  './data/data.json'


function TodoList() {
  const [todos, setTodos] = useState([]);

  
  const loadFromFile = data.map( ( data) => {
    const newTodo = addTodo(new Todo(data.id,data.text));
    return  ( {newTodo} )});


  const addTodo = todo => {
    if (!todo.text || /^\s*$/.test(todo.text)) {
      return;
    }

    const newTodos = [todo, ...todos];

    setTodos(newTodos);
    console.log(...todos);
  };

  const updateTodo = (todoId, newValue) => {
    if (!newValue.text || /^\s*$/.test(newValue.text)) {
      return;
    }

    setTodos(prev => prev.map(item => (item.id === todoId ? newValue : item)));
  };

  const removeTodo = id => {
    const removedArr = [...todos].filter(todo => todo.id !== id);

    setTodos(removedArr);
  };

  const completeTodo = id => {
    let updatedTodos = todos.map(todo => {
      if (todo.id === id) {
        todo.isComplete = !todo.isComplete;
      }
      return todo;
    });
    setTodos(updatedTodos);
  };

  return (
    <>
      <TodoForm onSubmit={addTodo} />
      {loadFromFile}
      <Todo 
        todos={todos}
        completeTodo={completeTodo}
        removeTodo={removeTodo}
        updateTodo={updateTodo}
      />
    </>
  );
}

export default TodoList;

我想创建 Todo 对象的新实例。我尝试了很多次,许多不同的形式,但仍然不起作用。我有一个来自 data.json 文件的 id 和一个文本。我想用这两个值创建 Todo 对象的实例。但是怎么做呢?

import React, { useState } from 'react';
import TodoForm from './TodoForm';
import EditIcon from '@material-ui/icons/Edit';
import DeleteIcon from '@material-ui/icons/Delete';


const Todo = ({ todos, completeTodo, removeTodo, updateTodo }) => {
  
  const [edit, setEdit] = useState({
    id: null,
    value: ''
  });

  const submitUpdate = value => {
    updateTodo(edit.id, value);
    setEdit({
      id: null,
      value: ''
    });
  };

  if (edit.id) {
    return <TodoForm edit={edit} onSubmit={submitUpdate} />;
  }

  return todos.map((todo, index) => (
    <div
      className={todo.isComplete ? 'todo-row complete' : 'todo-row'}
      key={index}
    >
      <p> <div key={todo.id} onClick={() => completeTodo(todo.id)}>
        {todo.text}
      </div> 
      </p>

      <div className='icons'>
        <DeleteIcon fontSize="small"
          onClick={() => removeTodo(todo.id)}
          className='delete-icon'
        />
        <EditIcon
          onClick={() => setEdit({ id: todo.id, value: todo.text })}
          className='edit-icon'
        />
      </div>
    </div>
  ));
};

export default Todo;

import React, { useState, useEffect, useRef } from 'react';
import { Fab, IconButton } from "@material-ui/core";
import AddIcon from '@material-ui/icons/Add';

function TodoForm(props) {
  const [input, setInput] = useState(props.edit ? props.edit.value : '');

  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus();
  });

  const handleChange = e => {
    setInput(e.target.value);
  };

  const handleSubmit = e => {
    e.preventDefault();

    props.onSubmit({
      id: Math.floor(Math.random() * 10000),
      text: input
    });
    setInput('');
  };

  return (
    <form onSubmit={handleSubmit} className='todo-form'>
      {props.edit ? (
        <>
          <textarea cols="10"
            placeholder='Update item'
            value={input}
            onChange={handleChange}
            name='text'
            ref={inputRef}
            className='todo-input edit'
          />
          <button onClick={handleSubmit} className='todo-button edit'>
            Save
          </button>
        </>
      ) : (
        <>
          <input
            placeholder='Add item'
            value={input}
            onChange={handleChange}
            name='text'
            className='todo-input'
            ref={inputRef}
          />
          
          <Fab color="primary" aria-label="add"> 
            < AddIcon onClick={handleSubmit} fontSize="small" /> 
          </Fab>
        </>
      )}
    </form>
  );
}

export default TodoForm;

【问题讨论】:

  • 该问题缺乏明确的问题陈述。不知道是什么问题。代码很庞大,无法调试。见stackoverflow.com/help/how-to-ask
  • 您的todo 对象似乎是至少具有idtextvalueisComplete 属性的对象。你还需要什么? TodoForm 调用 addTodo 并传递一个 todo 对象是做什么的?
  • 我想创建 Todo 对象的新实例。我尝试了很多次,许多不同的形式,但仍然不起作用。我有一个来自 data.json 文件的 id 和一个文本。我想用这两个值创建 Todo 对象的实例。但是怎么做呢?
  • 创建对象字面量是微不足道的,即{ id: 123, text: 'the todo text' }。请更新您的问题以包含所有相关代码,即请包含您尝试创建和添加待办事项对象的代码。
  • 刚刚用代码的最后一部分更新了我的问题。这就是我所拥有的,请告诉我如何将 data.json 文件中的值显示为一个待办事项(就像通过添加按钮添加的待办事项一样)

标签: javascript reactjs react-native react-hooks frontend


【解决方案1】:

问题

啊,我明白你现在的意思了,你想从外部文件加载一些待办事项列表。我在您的代码中看到的主要问题是您试图手动调用/构造 Todo React 组件,而这根本不是 React 的工作方式。您将数据/状态/道具渲染到 JSX 中并将其传递给 React,React 会处理实例化组件并计算渲染的 DOM。

const loadFromFile = data.map((data) => {
  const newTodo = addTodo(new Todo(data.id, data.text));
  return ({newTodo});
});

Todo 不应该被直接调用,React 会处理这个。

解决方案

由于data 看起来已经是具有idtext 属性的对象数组,因此它可以方便地匹配您在状态中存储的内容。您可以简单地将data 作为初始todos 状态值传递。

const [todos, setTodos] = useState(data);

如果数据不容易使用,您可以创建一个初始化函数来获取 data 并将其转换/映射到您的代码需要的对象形状。

const initializeState = () => data.map(item => ({
  id: item.itemId,
  text: item.dataPayload,
}));

const [todos, setTodos]= useState(initializeState);

运行示例:

import data from "./data.json";

function TodoList() {
  const [todos, setTodos] = useState(data); // <-- initial state

  const addTodo = (text) => {
    if (!text || /^\s*$/.test(text)) {
      return;
    }

    setTodos((todos) => [todo, ...todos]);
  };

  const updateTodo = (id, newTodo) => {
    if (!newTodo.text || /^\s*$/.test(newTodo.text)) {
      return;
    }

    setTodos((todos) => todos.map((todo) => (todo.id === id ? newTodo : todo)));
  };

  const removeTodo = (id) => {
    setTodos((todos) => todos.filter((todo) => todo.id !== id));
  };

  const completeTodo = (id) => {
    setTodos((todos) =>
      todos.map((todo) =>
        todo.id === id
          ? {
              ...todo,
              isComplete: !todo.isComplete
            }
          : todo
      )
    );
  };

  return (
    <>
      <TodoForm onSubmit={addTodo} />
      <Todo
        todos={todos}
        completeTodo={completeTodo}
        removeTodo={removeTodo}
        updateTodo={updateTodo}
      />
    </>
  );
}

【讨论】:

  • 天哪,你是救生员!!非常非常感谢!!!!!!!
  • 还有一个问题:如果我想写入文件并保存任何动作,我应该安装和使用“write-json-file”吗?是不是好办法?
  • @info_deniz 我对那个包没有任何经验,但当然,听起来值得一试。
  • 再次感谢您所做的一切!
猜你喜欢
  • 2017-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多