Должен ли я использовать один или несколько useEffect в компоненте?
У меня есть некоторые побочные эффекты, и я думаю, как их организовать:
- как одноразовый эффект
- или несколько useEffects
что лучше с точки зрения производительности и архитектуры?
3 ответа
Шаблон, которому вы должны следовать, зависит от вашего useCase.
Во-первых, у вас может возникнуть ситуация, когда вам нужно добавить прослушиватель событий во время первоначального монтирования и очистить их при размонтировании, а также другой случай, когда нужно вычистить и повторно добавить конкретного прослушивателя при смене проп. В таком случае лучше использовать два разных useEffect для сохранения соответствующей логики, а также для повышения производительности.
useEffect(() => {
// adding event listeners on mount here
return () => {
// cleaning up the listeners here
}
}, []);
useEffect(() => {
// adding listeners everytime props.x changes
return () => {
// removing the listener when props.x changes
}
}, [props.x])
Во-вторых: может быть случай, когда вам нужно инициировать вызов API или какой-либо другой побочный эффект, когда какое-либо состояние или реквизит изменяются среди набора. В таком случае один useEffect
с соответствующими значениями для мониторинга должно быть хорошей идеей
useEffect(() => {
// side effect here on change of any of props.x or stateY
}, [props.x, stateY])
Третий: третий случай, когда вам нужно предпринять разные действия при изменении разных значений. В таком случае разделите соответствующие сравнения на разные useEffects
useEffect(() => {
// some side-effect on change of props.x
}, [props.x])
useEffect(() => {
// another side-effect on change of stateX or stateY
}, [stateX, stateY])
Вы должны использовать несколько эффектов, чтобы разделить проблемы, как это предлагается по адресу actjs.org https://reactjs.org/docs/hooks-effect.html
Совершенно нормально иметь несколько useEffect.
Вот как выглядит одна из моих настроек:
/*
* Backend tags list have changed add the changes if needed
*/
useEffect(() => {
setTagsList(setTagsAdded);
}, [setTagsAdded]);
/*
* Backend files have changed add the changes if needed
*/
useEffect(() => {
for (let i = 0; i < changedFilesMeta.length; i += 1) {
// Is the list item value changed
if (changedFilesMeta[i].id === currentEditableFile.id) {
unstable_batchedUpdates(() => {
setTags(changedFilesMeta[i].tags ? changedFilesMeta[i].tags : []);
});
}
}
}, [changedFilesMeta]);
/*
* Reset when user select new files using the filepicker
*/
useEffect(() => {
if (setNewFiles.length > 0) {
unstable_batchedUpdates(() => {
setCurrentFile(null);
setDescription('');
setTitle('');
setTags([]);
});
}
}, [setNewFiles]);
/*
* User selecet to edit a file, change to that file
*/
useEffect(() => {
// When user select a file to edit it
if (currentEditableFile && currentEditableFile !== theCurrentFile) {
setCurrentFile(currentEditableFile);
unstable_batchedUpdates(() => {
setDescription(currentEditableFile.description);
setTitle(currentEditableFile.title);
setTags(currentEditableFile.tags);
});
}
}, [currentEditableFile]);