[英]How to update with React Hooks specific value of an array inside an object?
[英]React hooks updating component after value inside object inside another object changes - how to?
我試圖讓一個功能組件在 object 中的一個值發生更改后重新呈現 object:
所以項目有任務: project.tasks和project.completed_tasks
每個任務也是一個 object,它有一個屬性 is_completed: task.is_completed
一旦 is_completed 更改為 true 或 false,我希望Project comp.net 重新呈現任務的更新進度。
這在后端工作,但我無法讓它與 React 一起工作,並掛鈎 api。我猜它與淺比較與深度比較有關,但我已經在 tasksContext 的updateTask function 中創建了一個副本。
任何幫助,將不勝感激。 加粗以便更容易閱讀,因為它很多。
這是我要更改的組件:
const Project = ({project, formatDate}) => {
const tasksContext = useContext(TasksContext);
const {tasksCompleted} = tasksContext;
const [open, setOpen] = useState(false);
const [progress] = useState(tasksCompleted.filter(task => task.project_id === project.id).length);
return (
<Card.Content>
<Card.Header>
{project.name}
</Card.Header>
<Card.Meta>
{formatDate(project.start_date)} - {formatDate(project.end_date)}
</Card.Meta>
<Card.Description>
<Progress value={progress} total={project.total_tasks} progress='ratio' warning/>
</Card.Description>
</Card.Content>
<Card.Content extra>
<List celled horizontal size="mini" floated="right">
<List.Item as="a" onClick={handleEdit}>Edit</List.Item>
<List.Item as="a" onClick={handleDelete}>Delete</List.Item>
</List>
<Confirm
open={open}
onCancel={handleCancel}
onConfirm={handleConfirm}
cancelButton='Never mind'
confirmButton="Let's do it"
size='mini'
/>
</Card.Content>
)
};
這是我的 tasksContext 掛鈎:
import React, {createContext, useState} from 'react';
import PropTypes from "prop-types";
export const TasksContext = createContext({});
export const TasksProvider = props => {
//initial values obtained from props
const {
tasks: initialTasks,
tasksCompleted: initialTasksCompleted,
children
} = props;
//state to keep the values
const [tasks, setTasks] = useState(initialTasks);
const [tasksCompleted, setTasksCompleted] = useState(initialTasksCompleted);
//============== TASK FUNCTIONS ===================//
const getTasks = () => {
const token = localStorage.getItem('token');
const getObj = {
'method': 'GET',
'headers': {
'Authorization': `Bearer ${token}`
}
}
const tasksUrl = `http://localhost:3000/tasks`;
fetch(tasksUrl, getObj)
.then(res => res.json())
.then(tasks => {
setTasks(tasks)
getTasksCompleted(tasks)
})
}
const getTasksCompleted = (tasks) => {
const completedTasks = tasks.filter(task => task.is_completed === true);
setTasksCompleted(completedTasks);
}
const updateTask = (task) => {
const updatedTasks = [...tasks];
const index = updatedTasks.findIndex(taskToUpdate => taskToUpdate.id === task.id);
updatedTasks[index] = task;
setTasks(updatedTasks);
getTasksCompleted(updatedTasks);
}
//make the context object
const tasksContext = {
tasks,
setTasks,
tasksCompleted,
getTasks,
updateTask
};
return <TasksContext.Provider value={tasksContext}>{children}</TasksContext.Provider>
};
export const {TasksConsumer} = TasksContext;
TasksProvider.propTypes = {
tasks: PropTypes.array,
tasksCompleted: PropTypes.array
};
TasksProvider.defaultProps = {
tasks: [],
tasksCompleted: []
};
這是調用 updateTask function 的另一個組件:
const Task = ({task}) => {
const tasksContext = useContext(TasksContext);
const {updateTask} = tasksContext;
const [name, setName] = useState(task.name);
const [checked, setChecked] = useState(task.is_completed);
const [editing, setEditing] = useState(task.name ? false : true);
const editTask = (name, is_completed) => {
const taskUrl = `http://localhost:3000/tasks/${task.id}`
const token = localStorage.getItem('token')
const taskObj = {
'method': 'PATCH',
'headers': {
"Accept": "application/json",
'Authorization': `Bearer ${token}`,
"Content-Type": "application/json"
},
'body': JSON.stringify({name, is_completed})
}
fetch(taskUrl, taskObj)
.then(res => res.json())
.then(task => {
setName(name);
updateTask(task);
})
}
...render function etc
在您的功能組件中像這樣嘗試useEffect()
:
const tasksContext = useContext(TasksContext);
useEffect(() => {
tasksContext
}, [...Object.values(tasksContext]);
這將查找值本身的變化,並應在適當的時間觸發useContext()
。
我認為問題在於您如何跟蹤項目組件的進度:
const [progress] = useState(tasksCompleted.filter(task => task.project_id === project.id).length);
此行僅初始化progress
的值。 如果您希望組件重新呈現,則需要在tasksCompleted
更改后更改進度值。 假設tasksCompleted
正確更改,您可以使用useEffect
觀察變量並更新progress
state。
const [progress, setProgress] = useState(tasksCompleted.filter(task => task.project_id === project.id).length);
useEffect(() => {
setProgress(tasksCompleted.filter(task => task.project_id === project.id).length)
}, [tasksCompleted])
useEffect 中指定的 Function 將在第一次呈現時運行,並且每次數組中的值發生變化時。 由於它更新了 state,它也會觸發重新渲染。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.