React Hooks: Handling Objects as dependency in useEffects

混江龙づ霸主 提交于 2020-11-28 09:15:33

问题


UPDATE: Yes for use case 1, if I extract search.value outside the useEffect and use it as a dependency it works.

But I have an updated Use case below

Use Case 2: I want to pass a searchHits Object to the server. The server in turn return it back to me with an updated value in response. If I try using the searchHits Object I still get the infinite loop

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])

Use Case 1: I want to search for a string and then highlight when I get results

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])

In useEffect I make the API call using search.value. eslint complains that there is a dependency on state.search , it does not recognize state.search.value. Even if you pass state.search.value it complains about state.search

Now if you pass state.search as dependecy it goes in an infinite loop because after the api call we are updating the highlights flag inside search.

Which will trigger another state update and a recursive loop.

One way to avoid this is to not have nested Objects in state or move the highlights flag outside search, but I am trying to not go that route give the sheer dependecies I have. I would rather have an Object in state called search the way it is. Is there any way to better approach this. If I want to keep my state Object as above how do I handle the infinite loop


回答1:


Just a eslint stuff bug may be. You have retracted some code by saying //do something and have hidden he code. Are you sure that it doesn't have anything to do with search object?

Also, try to extract the variable out before useEffect().

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

If your search value is an object, react does shallow comparison and it might not give desired result. Re-rendering on a set of object dependencies isn't ideal. Extract the variables.

React does shallow comparison of dependencies specified in useEffect

eg.,

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

Additionally, you can add dev dependency for eslint-plugin-react-hooks, to identify common errors with hooks



来源:https://stackoverflow.com/questions/58422597/react-hooks-handling-objects-as-dependency-in-useeffects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!