Реагировать на хуки: обработка объектов как зависимости в useEffects

ОБНОВЛЕНИЕ: Да для варианта использования 1, если я извлекаю search.value вне useEffect и использую его как зависимость, он работает.

Но у меня есть обновленный вариант использования ниже

Вариант использования 2: я хочу передать объект searchHits серверу. Сервер, в свою очередь, возвращает его мне с обновленным значением в ответ. Если я попытаюсь использовать объект searchHits, я все равно получу бесконечный цикл

state: {
    visible: true,
    loading: false,
    search: {
        value: “”,
        searchHits: {....}, 
        highlight: false,
    }
}

let val = search.value
let hits = search.searchHits
useEffect( () => {

    axios.post(`/search=${state.search.value}`, {hits: hits}).then( resp => {
        …do something or ..do nothing
        state.setState( prevState => {
            return {
                …prevState,
                search: {... prevState.search, hits: resp.hit}
            }
        })
    })
}, [val, hits])

Вариант использования 1: я хочу найти строку, а затем выделить ее, когда получу результаты.

e.g.

state: {
    visible: true,
    loading: false,
    search: {
        value: “”,
        highlight: false,
    }
}

useEffect( () => {

    axios.get(`/search=${state.search.value}`).then( resp => {
        …do something or ..do nothing
        state.setState( prevState => {
            return {
                …prevState,
                search: {... prevState.search, highlight: true}
            }
        })
    })
}, [state.search])

В useEffect я вызываю API с помощью search.value. eslint жалуется, что есть зависимость от state.search, он не распознает state.search.value. Даже если вы сдадите state.search.value, он жалуется на state.search

Теперь, если вы передадите state.search в качестве зависимости, он перейдет в бесконечный цикл, потому что после вызова api мы обновляем флаг highlights внутри поиска.

Это вызовет еще одно обновление состояния и рекурсивный цикл.

Один из способов избежать этого - не иметь вложенных объектов в состоянии или переместить флаг выделения за пределы поиска, но я пытаюсь не идти по этому маршруту, давая явные зависимости, которые у меня есть. Я бы предпочел, чтобы объект находился в состоянии, называемом поиском, каким он есть. Есть ли способ лучше подойти к этому. Если я хочу сохранить свой объект состояния, как указано выше, как мне справиться с бесконечным циклом


person Stallion V    schedule 16.10.2019    source источник
comment
Это постоянная проблема с линтерами и их взаимодействием с перехватчиками реакции. В вашем коде нет ничего плохого. Как есть, это предупреждение можно проигнорировать.   -  person Cool Guy    schedule 17.10.2019
comment
Если это проблема esLint, я с удовольствием проигнорирую ее, но я действительно хочу быть уверенным. Потому что проблема возникает только тогда, когда мы используем объекты внутри зависимостей.   -  person Stallion V    schedule 18.10.2019
comment
Избегайте использования больших объектов с useState. Если необходимо, сделайте это с помощью useReducer.   -  person Samer Buna    schedule 20.10.2019
comment
@SamerBuna Я использовал useReducers, и он все еще зацикливается.   -  person Stallion V    schedule 23.10.2019


Ответы (1)


Может быть просто ошибка в eslint. Вы отозвали код, сказав //do something, и скрыли его. Вы уверены, что это не имеет отношения к поисковому объекту?

Также попробуйте извлечь переменную до useEffect().

const searchValue = state.search.value; useEffect(()=>{// axios call here},[searchValue])

Если поисковым значением является объект, response выполняет поверхностное сравнение, и это может не дать желаемого результата. Повторный рендеринг набора зависимостей объектов не идеален. Извлеките переменные.

React выполняет поверхностное сравнение зависимостей, указанных в useEffect

eg.,

const {searchParam1, searchParam2} = search.value;
useEffect(() => {
//logic goes here
}, [searchParam1, searchParam2]);

Кроме того, вы можете добавить зависимость разработчика для eslint-plugin-react-hooks, чтобы определять распространенные ошибки с помощью хуков.

person Karthik R    schedule 17.10.2019
comment
делать что-то не имеет ничего существенного и может быть удалено. Да Извлечение переменной работает, но тогда оно работает только потому, что search.value является строкой. Если search.value - это объект, он по-прежнему заходит в бесконечный цикл - person Stallion V; 18.10.2019
comment
@StallionV передача объекта в качестве зависимости useEffect - плохая идея. В общем, вам не нужен повторный рендеринг на основе объекта, а скорее набора переменных. React будет проводить поверхностное сравнение объектов, а не глубокое сравнение. Так что извлеките все необходимые переменные из search.value и добавьте их как зависимости. Буду обновлять ответы - person Karthik R; 19.10.2019
comment
Я это понимаю. Но как тогда решить проблему обновления объектов состояния на основе ответа API. API-интерфейсы должны быть с useEffect. Если я хочу опубликовать этот объект на сервере, он должен быть зависимостью. Теперь в этом случае, как мне обновить на основе ответа сервера и избежать бесконечного цикла - person Stallion V; 23.10.2019
comment
Подумайте об этом в практической ситуации. вы делаете это useeffect, что означает, что вы хотите, чтобы эти данные были основаны на некоторых переменных при запуске. Если вы хотите, чтобы это произошло только один раз, вы передаете empty [] как зависимость, иначе, если вы хотите, чтобы это происходило при изменении переменной, добавьте их как зависимость. Обычно post on useEffect - это редкий вызов, и мне интересно, какие из таких сценариев применимы. - person Karthik R; 23.10.2019
comment
Ситуация может заключаться в том, что вы передаете некоторый объект данных из своего состояния на сервер, который, в свою очередь, массирует данные, изменяет их и передает обратно вам. Теперь вам нужно обновить эти данные обратно в состоянии. - person Stallion V; 23.10.2019