У меня есть некоторые побочные эффекты, которые нужно применить в моем компоненте реакции, и я хочу знать, как их организовать:
Что лучше с точки зрения производительности и архитектуры?





Шаблон, которому вам нужно следовать, зависит от вашего варианта использования.
Первый: У вас может быть ситуация, когда вам нужно добавить прослушиватель событий во время первоначального монтирования и очистить их при размонтировании, а также другой случай, когда конкретный слушатель необходимо очистить и повторно добавить при изменении свойства.
В таком случае использование двух разных 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])
Третий: Вам нужен отдельный побочный эффект для разных наборов изменений. В таком случае разделите соответствующие побочные эффекты на разные useEffect.
useEffect(() => {
// some side-effect on change of props.x
}, [props.x])
useEffect(() => {
// another side-effect on change of stateX or stateY
}, [stateX, stateY])
как насчет золотой середины между примерами Второй и Третий выше ?: у вас есть логика, которая запускается при изменении подмножества состояний / реквизитов, но у каждого есть отдельная логика, которая должна выполняться в дополнение к некоторому общему коду, который необходимо запустить? Вы бы не стали использовать [] (потому что это все еще подмножество состояний / свойств, для которых вы ожидаете изменений), но вы также хотели бы повторно использовать код. Вы используете отдельный useEffects и помещаете общий код в функцию, которую каждый из них вызывает отдельно?
Как следует из ответа ниже, команда React предлагает разделить перехватчики по интересам, чтобы вы разбили их на несколько вызовов useEffect.
Всегда ли они запускаются в порядке их определения? т.е. сначала всегда вызывается эффект1, затем эффект2?
@computrius да, React will apply every effect used by the component, in the order they were specified.
Что, если у меня есть несколько эффектов componentDidMount (пустой массив []), но они делают разные вещи? я должен использовать их в одном useEffect или в нескольких?
Вы должны использовать несколько эффектов для отдельные проблемы как предложено reactjs.org.
Я знаю, но ваш ответ улучшился бы, если бы вы объяснили, почему разделение ответственности, и является ли это архитектурной концепцией или концепцией производительности.
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - Из обзора
Идеально иметь отлично для множественного 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]);
не могли бы вы добавить еще немного своего кода, чтобы прояснить, какой бит состояния обновляется setTags? setTagsAdded - это функция или объект? Также как вы убедились, что «производительность и архитектура» лучше, чем один большой useEffect?
Я не думаю, что включение этого кода, особенно вне контекста, полезно или имеет отношение к вопросу.
@Bricky, несмотря ни на что, удаление всего кода И добавление цитаты слишком сильно меняет ответ, чтобы его оправдать
Цитата находится в соответствующем разделе по ссылке. Простое включение ссылки - легкий ответ.
Это, вероятно, имеет значение в зависимости от вашего варианта использования, но я собираюсь отредактировать ваш вопрос, чтобы прояснить, что это касается общих советов.