reactjs - React Hooks, how to handle dependency If i want to run only when one of them changes?
问题描述
I wanted to ask if there's a proper way of handling a situation when we have an useEffect that we only care it runs when one variable of the dependency array is changed.
We have a table that has pagination and inputs to filter the content with a button.
When the user changes the action (inputs) we update this state and when the user press search we fetch from the api.
When we have results paginated, we then hook on the page and if it changes we then fetch the corresponding page.
I solved the issue by having the ref of action and checking if the previous value was different from the current value. Though I don't know if this is the best practice
I did something like this.
const FunctionView = () => {
const actionRef = useRef({})
// action object have query params for the api
const fetchData = useCallback((page) => {
// call and api and sets local values
}, [action])
// this hook handle page next or previous
useEffect(() => {
let didCancel = false
if (isEqual(Object.values(action), Object.values(actionRef.current))) {
if (!didCancel) fetchData(page + 1)
}
actionRef.current = action
return () => {
didCancel = true
}
}, [page, fetchData, action])
return (
<>
Components here that changes {action} object, dates and category
<Button onClick={() => fetchData(page)}>Search</Button>
<Table>...</Table>
</>
)
}
I know I can set the dependency array to only page but react lint plugin complains about this so I ended up with warnings.
解决方案
A common mistake is trying to directly wire the state of forms up to the data they represent. In your example, you DO want to perform the search when action
changes. What you're actually trying to avoid is updating action
every time one of the inputs changes prior to submit.
Forms are, by nature, transient. The state of the form is simply the current state of the inputs. Unless you really want things to update on every single keystroke, the storage of these values should be distinct.
import { useCallback, useEffect, useState } from 'react'
const Search = () => {
const [action, setAction] = useState({})
const loadData = useCallback(() => {
// call api with values from `action`
}, [action])
useEffect(loadData, [loadData])
return (
<>
<SearchForm setRealData={setAction} />
<Table>...</Table>
</>
)
}
const SearchForm = ({ setRealData }) => {
// don't want to redo the search on every keystroke, so
// this just saves the value of the input
const [firstValue, setFirstValue] = useState('')
const [secondValue, setSecondValue] = useState('')
const handleFirstChange = (event) => setFirstValue(event.target.value)
const handleSecondChange = (event) => setSecondValue(event.target.value)
// now that we have finished updating the form, update the state
const handleSubmit = (event) => {
event.preventDefault()
setRealData({ first: firstValue, second: secondValue })
}
return (
<form onSubmit={handleSubmit}>
<input value={firstValue} onChange={handleFirstChange} />
<input value={secondValue} onChange={handleSecondChange} />
<button type="submit">Search</button>
</form>
)
}
推荐阅读
- php - php发送电子邮件不起作用
- html - z-index 不适用于相对父级和后/前元素
- jquery - jQuery.ajax 在 IE11 中返回空响应文本
- python - 如何在所有 xml 文件上调用 .py?
- bash - 使用 sed 提取行块
- javascript - 事件命名空间在“mouseup”事件中不起作用
- division - Graphite divideSeries 错误结果
- ssis - 使用 PowerShell 2.0 创建 SSIS 文件夹
- c++ - 根据 Pugixml 中的子值删除节点
- php - 在 Woocommerce 中的产品简短描述之后显示自定义字段值