使用钩子将状态提升到 React 应用程序中的主要组件
Lifting up the state to the main component in React application using hooks
我正在学习 reactjs 并尝试实现一些小东西来练习。这个想法很简单,将记录 (feedbackTasks
) 添加到数据库并列出这些记录(当第一次加载页面时以及稍后添加新记录时)。请看下图。
主要成分是ManageFeedbackTasks
。我将 feedbackTask
项的列表保持在其状态 (st_feedbackTaskList
)。此列表的更新是通过 add_to_st_feedbackTask
函数执行的。如果第一次生成此列表,所有获取的数据(来自 PrintFeedbackTasks
组件)将设置为 st_feedbackTaskList
。如果不是,则仅将添加的项目(来自 ShowAddingFeedbackTaskForm
)插入列表中。
export function ManageFeedbackTasks() {
const [st_feedbackTaskList, setFeedbackTaskList] = useState([]);
const add_to_st_feedbackTask = (data) => {
if (st_feedbackTaskList.length == 0) {
setFeedbackTaskList(data);
} else {
const { id, title, description } = data;
setFeedbackTaskList([...st_feedbackTaskList, { id, title, description }]);
}
}
return (
<>
<ShowAddingFeedbackTaskForm onAddingItem={add_to_st_feedbackTask} />
<PrintFeedbackTasks onListingFeedbackTasks={add_to_st_feedbackTask} feedbackTasks={st_feedbackTaskList} />
</>
);
}
下面是PrintFeedbackTasks
函数。此函数从主要组件 ManageFeedbackTasks
接收 feedbackTasks
列表。此列表是第一次使用 fetchFeedbackTasks
从数据库中获取。在 fetchFeedbackTasks
中,props.onListingFeedbackTasks(response.data)
将获取的列表发送回主组件以更新状态 (st_feedbackTaskList
)。
const PrintFeedbackTasks = (props) => {
const [st_isInitialized, setInitialized] = useState(false);
const fetchFeedbackTasks = () => {
axios.get('api/FeedbackTask/Index')
.then(response => props.onListingFeedbackTasks(response.data))
.catch(error => console.log(error));
}
useEffect(() => {
if (!st_isInitialized) {
fetchFeedbackTasks();
}
setInitialized(true);
});
return (
<React.Fragment>
{
props.feedbackTasks.map(taskItem =>....
}
</React.Fragment>
);
}
下面的组件显示添加表单并处理表单提交。添加新项目时,使用 props.onAddingItem
.
再次将该新项目发送回主组件
const ShowAddingFeedbackTaskForm = (props) => {
const [st_title, setTitle] = useState('');
const [st_description, setDescription] = useState('');
const handleSubmit = async (event) => {
event.preventDefault();
await axios(...)
.then(function (response) {
setTitle('');
setDescription('');
//This will update the list of the feedback task in the main component
props.onAddingItem({
id: response.data,
title: st_title,
description: st_description
});
//GET THE ID HERE
console.log(response.data);
}).catch(function (error) {
console.log(error);
});
}
return (
<form onSubmit={handleSubmit}>
<input
placeholder="Title..."
type="text"
value={st_title}
onChange={(event) => setTitle(event.target.value)}
/>
<input
placeholder="Description..."
type="text"
value={st_description}
onChange={(event) => setDescription(event.target.value)}
/>
<button>Add Feedback Task</button>
</form>
);
}
不知道这种提升和管理状态的方式是否健壮。有什么改进代码的建议吗?另外,我想知道是否应该将这些组件放到它们自己的页面中(例如,一个页面或添加一条记录,另一个用于列表)。这在 react
世界中是否更有意义?
将状态提升到父级的想法是正确的。但是,由于您的代码结构,您可能会导致大量重新渲染,并且可以在您的解决方案中进行一些性能优化。还有一件事是,与其在 PrintFeedbackTasks
组件中获取 feedbackTasks,不如在父组件中获取。 useEffect 还带有第二个参数,您可以使用它在初始挂载时执行它
您也可以使用 useCallback
挂钩来记忆函数。
管理反馈任务
export function ManageFeedbackTasks() {
const [st_feedbackTaskList, setFeedbackTaskList] = useState([]);
const fetchFeedbackTasks = useCallback(() => {
axios.get('api/FeedbackTask/Index')
.then(response => props.onListingFeedbackTasks(response.data))
.catch(error => console.log(error));
}, []);
useEffect(() => {
fetchFeedbackTasks();
}, []);
const add_to_st_feedbackTask = useCallback((data) => {
setFeedbackTaskList(prevTaskList => {
if (prevTaskList.length == 0) {
return data;
} else {
const { id, title, description } = data;
return [...prevTaskList, { id, title, description }];
}
});
}, [])
return (
<>
<ShowAddingFeedbackTaskForm onAddingItem={add_to_st_feedbackTask} />
<PrintFeedbackTasks onListingFeedbackTasks={add_to_st_feedbackTask} feedbackTasks={st_feedbackTaskList} />
</>
);
}
打印反馈任务
const PrintFeedbackTasks = (props) => {
return (
<React.Fragment>
{
props.feedbackTasks.map(taskItem =>....
}
</React.Fragment>
);
}
就拆分显示和更新任务列表的想法而言,它是产品决策,可以根据用户需要一次填写的字段列表的长度来做出决定
我正在学习 reactjs 并尝试实现一些小东西来练习。这个想法很简单,将记录 (feedbackTasks
) 添加到数据库并列出这些记录(当第一次加载页面时以及稍后添加新记录时)。请看下图。
主要成分是ManageFeedbackTasks
。我将 feedbackTask
项的列表保持在其状态 (st_feedbackTaskList
)。此列表的更新是通过 add_to_st_feedbackTask
函数执行的。如果第一次生成此列表,所有获取的数据(来自 PrintFeedbackTasks
组件)将设置为 st_feedbackTaskList
。如果不是,则仅将添加的项目(来自 ShowAddingFeedbackTaskForm
)插入列表中。
export function ManageFeedbackTasks() {
const [st_feedbackTaskList, setFeedbackTaskList] = useState([]);
const add_to_st_feedbackTask = (data) => {
if (st_feedbackTaskList.length == 0) {
setFeedbackTaskList(data);
} else {
const { id, title, description } = data;
setFeedbackTaskList([...st_feedbackTaskList, { id, title, description }]);
}
}
return (
<>
<ShowAddingFeedbackTaskForm onAddingItem={add_to_st_feedbackTask} />
<PrintFeedbackTasks onListingFeedbackTasks={add_to_st_feedbackTask} feedbackTasks={st_feedbackTaskList} />
</>
);
}
下面是PrintFeedbackTasks
函数。此函数从主要组件 ManageFeedbackTasks
接收 feedbackTasks
列表。此列表是第一次使用 fetchFeedbackTasks
从数据库中获取。在 fetchFeedbackTasks
中,props.onListingFeedbackTasks(response.data)
将获取的列表发送回主组件以更新状态 (st_feedbackTaskList
)。
const PrintFeedbackTasks = (props) => {
const [st_isInitialized, setInitialized] = useState(false);
const fetchFeedbackTasks = () => {
axios.get('api/FeedbackTask/Index')
.then(response => props.onListingFeedbackTasks(response.data))
.catch(error => console.log(error));
}
useEffect(() => {
if (!st_isInitialized) {
fetchFeedbackTasks();
}
setInitialized(true);
});
return (
<React.Fragment>
{
props.feedbackTasks.map(taskItem =>....
}
</React.Fragment>
);
}
下面的组件显示添加表单并处理表单提交。添加新项目时,使用 props.onAddingItem
.
const ShowAddingFeedbackTaskForm = (props) => {
const [st_title, setTitle] = useState('');
const [st_description, setDescription] = useState('');
const handleSubmit = async (event) => {
event.preventDefault();
await axios(...)
.then(function (response) {
setTitle('');
setDescription('');
//This will update the list of the feedback task in the main component
props.onAddingItem({
id: response.data,
title: st_title,
description: st_description
});
//GET THE ID HERE
console.log(response.data);
}).catch(function (error) {
console.log(error);
});
}
return (
<form onSubmit={handleSubmit}>
<input
placeholder="Title..."
type="text"
value={st_title}
onChange={(event) => setTitle(event.target.value)}
/>
<input
placeholder="Description..."
type="text"
value={st_description}
onChange={(event) => setDescription(event.target.value)}
/>
<button>Add Feedback Task</button>
</form>
);
}
不知道这种提升和管理状态的方式是否健壮。有什么改进代码的建议吗?另外,我想知道是否应该将这些组件放到它们自己的页面中(例如,一个页面或添加一条记录,另一个用于列表)。这在 react
世界中是否更有意义?
将状态提升到父级的想法是正确的。但是,由于您的代码结构,您可能会导致大量重新渲染,并且可以在您的解决方案中进行一些性能优化。还有一件事是,与其在 PrintFeedbackTasks
组件中获取 feedbackTasks,不如在父组件中获取。 useEffect 还带有第二个参数,您可以使用它在初始挂载时执行它
您也可以使用 useCallback
挂钩来记忆函数。
管理反馈任务
export function ManageFeedbackTasks() {
const [st_feedbackTaskList, setFeedbackTaskList] = useState([]);
const fetchFeedbackTasks = useCallback(() => {
axios.get('api/FeedbackTask/Index')
.then(response => props.onListingFeedbackTasks(response.data))
.catch(error => console.log(error));
}, []);
useEffect(() => {
fetchFeedbackTasks();
}, []);
const add_to_st_feedbackTask = useCallback((data) => {
setFeedbackTaskList(prevTaskList => {
if (prevTaskList.length == 0) {
return data;
} else {
const { id, title, description } = data;
return [...prevTaskList, { id, title, description }];
}
});
}, [])
return (
<>
<ShowAddingFeedbackTaskForm onAddingItem={add_to_st_feedbackTask} />
<PrintFeedbackTasks onListingFeedbackTasks={add_to_st_feedbackTask} feedbackTasks={st_feedbackTaskList} />
</>
);
}
打印反馈任务
const PrintFeedbackTasks = (props) => {
return (
<React.Fragment>
{
props.feedbackTasks.map(taskItem =>....
}
</React.Fragment>
);
}
就拆分显示和更新任务列表的想法而言,它是产品决策,可以根据用户需要一次填写的字段列表的长度来做出决定