如何在React中映射期间将组件推送到两个不同的div ?



在React中,我有一个对象数组作为状态。假设他们是"todos"。我也有两个div。一个div用于未完成的任务,第二个用于已完成的任务。在映射过程中,我使用组件。

const [todos, setTodos] = useState([
{id: 1, text: 'Lorem', isComplete: true},
{id: 2, text: 'Ipsum', isComplete: true}],
{id: 3, text: 'Test', isComplete: false})
]);
作为回报,我有一个HTML结构:
return (     
<div>
<h1>Todos</h1>
<p>My todos for today:</p>
<div id="incomplete"></div> 
<p>Todos that've been already done:</p>
<div id="complete"></div>     
</div> )

映射看起来像这样:

todos.map(todo => {     
if(todo.isComplete){
return <Todo 
id={todo.id} 
text={todo.text} 
isComplete={todo.isComplete}/>         
// AND HERE I WANT TO PUSH THIS COMPONENT INTO div#complete.     
} })

我期待这样的东西:

return (
<div>         
<h1>Todos</h1>
<p>My todos for today:</p>
<div id="incomplete">
<div className="task">
<p>Test</p>
</div>
<div className="task">
<p>Ipsum</p>
</div>
</div>
<p>Todos that've been already done:</p>
<div id="complete">
<div className="task">
<p>Lorem</p>
</div>
</div>
</div> )

更具体地说,我想让它更清楚,不要重复返回<Todo…>组件。

有可能吗?

这是我的原始代码,它看起来不太漂亮tbh

<div className='tasks'>
<h2>Tasks</h2>
<div className="tasks-incomplete">
<h3>Zadania do wykonania</h3>
{incompleteTasks.length > 0 && incompleteTasks.map(task => (
<Task 
key={task.id}
id={task.id} 
text={task.text} 
isComplete={task.isComplete} 
dateStart={task.dateStart}
dateComplete={task.dateComplete}
handleDeleteTask={() => handleDeleteTask(task.id)}
handleClickEdit={()=>handleClickEdit(task.id, task.text)}
handleComplete={()=>handleComplete(task.id)}
/>
))}
{incompleteTasks.length === 0 && <p>brak zadań</p>}
</div>

{completeTasks.length > 0 && (
<div id="completed" className="tasks-complete">
<h3>Zadania wykonane</ h3>
{completeTasks.map( task => (
// todo: task do destrukturyzacji
<Task 
key={task.id}
id={task.id} 
text={task.text} 
isComplete={task.isComplete} 
dateStart={task.dateStart}
dateComplete={task.dateComplete}
handleDeleteTask={()=>handleDeleteTask(task.id)}
handleClickEdit={()=>handleClickEdit(task.id, task.text)}
handleComplete={()=>handleComplete(task.id)}
/> 
))}
</div>
)}

</div>
)

map()之前使用filter(),只得到(in)/complete:

return (     
<div>
<h1>Todos</h1>
<p>My todos for today:</p>
<div id="incomplete">
{todos.filter(t => !t.isComplete).map(e => <Todo ...{} />)}
</div> 
<p>Todos that've been already done:</p>
<div id="complete">
{todos.filter(t => t.isComplete).map(e => <Todo ...{} />)}
</div>     
</div> 
)

反应演示:

const { useState } = React;
const Todo = (props) => {
return <p>{props.text}</p>;
}
const Example = () => {
const [todos, setTodos] = useState([
{id: 1, text: 'Lorem', isComplete: true},
{id: 2, text: 'Ipsum', isComplete: true},
{id: 3, text: 'Test', isComplete: false}
]);
return (     
<div>
<h1>Todos</h1>
<p>My todos for today:</p>
<div id="incomplete">
{todos.filter(t => !t.isComplete).map(e => <Todo {...e} />)}
</div> 
<p>Todos that've been already done:</p>
<div id="complete">
{todos.filter(t => t.isComplete).map(e => <Todo {...e} />)}
</div>     
</div> 
);
}
ReactDOM.render(<Example />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>


基于OP的编辑,您可以引入像getTodos这样接受布尔值的函数,并在此基础上创建过滤器函数。然后返回相应的<Todo />,这将减少重复的filter(),map()<Todo ... />,所以你只需要render中的这两个:

<div id="incomplete">
{getTodos()}
</div> 
// ....
<div id="complete">
{getTodos(true)}
</div>   

反应演示:

const { useState } = React;
const Todo = (props) => {
return <p>{props.text}</p>;
}
const Example = () => {
const [todos, setTodos] = useState([
{id: 1, text: 'Lorem', isComplete: true},
{id: 2, text: 'Ipsum', isComplete: true},
{id: 3, text: 'Test', isComplete: false}
]);

const getTodos = (complete) => {
const filterFunction = (complete) ? (t => t.isComplete) : (t => !t.isComplete);
return todos.filter(filterFunction).map(e => {
return <Todo {...e} />;
});
}
return (     
<div>
<h1>Todos</h1>
<p>My todos for today:</p>
<div id="incomplete">
{getTodos()}
</div> 
<p>Todos that've been already done:</p>
<div id="complete">
{getTodos(true)}
</div>     
</div> 
);
}
ReactDOM.render(<Example />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

您可以编写一个函数来根据任务状态创建所需的jsx,使用它来呈现任务,请参阅下面的代码片段

const [todos, setTodos] = useState([
{ id: 1, text: "task1", isComplete: false },
{ id: 2, text: "task2", isComplete: false },
{ id: 3, text: "task3", isComplete: true }
]);
const tasks = () => {
let completeTasks = [];
let incompleteTasks = [];
todos.forEach((todo) => {
if (todo.isComplete) {
completeTasks.push(
<div className="task">
<p>{todo.text}</p>
</div>
);
} else {
incompleteTasks.push(
<div className="task">
<p>{todo.text}</p>
</div>
);
}
});
return { complete: completeTasks, incomplete: incompleteTasks };
};
const todoElements = tasks();
return (
<div className="App">
<h1>Todos</h1>
<div>
<p>My todos for today:</p>{" "}
<div id="incomplete">{todoElements.incomplete}</div>
<p>Todos that've been already done:</p>
<div id="complete">{todoElements.complete}</div>
</div>
</div>
);

请参考沙盒:https://codesandbox.io/s/quizzical-leavitt-utt31m?file=/src/App.js:91-1107

最新更新