Я изучаю реакцию и пытаюсь реализовать небольшие вещи для практики. Идея проста: добавлять записи (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
. Эта функция получает список feedbackTasks
от основного компонента ManageFeedbackTasks
. Этот список впервые извлекается из базы данных с помощью 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.info(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.info(response.data);
}).catch(function (error) {
console.info(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
мире?
Идея поднять состояние до родителя правильная. Однако из-за структуры вашего кода вы можете вызвать много повторных рендеров, и в вашем решении можно сделать несколько оптимизаций производительности. Еще одна вещь заключается в том, что вместо того, чтобы получать FeedbackTasks в компоненте PrintFeedbackTasks
, вы должны делать это в самом родителе. Также 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.info(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} />
</>
);
}
PrintFeedbackTasks
const PrintFeedbackTasks = (props) => {
return (
<React.Fragment>
{
props.feedbackTasks.map(taskItem =>....
}
</React.Fragment>
);
}
Что касается идеи разделения показа и обновления TaskList, то это как продуктовое решение, которое может быть принято в зависимости от того, насколько длинный список полей, которые пользователь должен заполнить сразу