javascript - 如何在 React.. 中创建对象的实例?
问题描述
我对 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;
解决方案
问题
啊,我知道你现在得到了什么,你想从外部文件加载一些待办事项列表。我在您的代码中看到的主要问题是您试图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
的对象数组,因此它可以方便地匹配您在 state 中存储的内容。您可以简单地作为初始状态值传递。id
text
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}
/>
</>
);
}
推荐阅读
- c# - 测试字符串值是否包含在字符串数组中
- python - Flask SocketIO 不向分配的房间发送消息
- blockchain - 在 React Typescript Web 应用程序(克隆的 create-daml-app)上的 DABL 项目中使用派对 ID
- java - 生成大量小pdf文件
- javascript - Javascript - 检测广告拦截器检测器
- matlab - 在 Matlab 中求解积分符号
- angular - 选择日期选择器材质后如何格式化数据?
- python - 比较每个项目中具有多个值的两个列表
- pdf - Libreoffice Writer(无头和非无头)在将 pdf 导出为 PDF/A 后删除其签名
- java - 使用 postDelayed 延迟打开片段是一个好习惯吗?