[英]React.useCallback() for chained anonymous functions
Often, in order to pass an onChange
callback function to a component you do something like this:通常,为了将
onChange
回调函数传递给组件,您可以执行以下操作:
const handleChange = (e) => {
console.log(e.target.value)
}
return (
<Component onChange={handleChange} />
)
If you don't want the Component
to render every time the main component does, you must wrap it in a React.useCallback()
hook as follow:如果你不希望
Component
来呈现每个主要成分做的时候,你必须在其包装React.useCallback()
挂钩如下:
const handleChange = React.useCallback((e) => {
console.log(e.target.value)
}, [])
return (
<Component onChange={handleChange} />
)
In a case where this input is generated in a for loop based on a list, you want the callback to know about the source of the change.在基于列表在 for 循环中生成此输入的情况下,您希望回调知道更改的来源。 The most common way of passing the information is by chaining lambdas as follow:
传递信息的最常见方式是按如下方式链接 lambda:
const fields = ['field1', 'field2', 'field3']
const handleChange = (fieldName) => (e) => {
console.log(`${fieldName}: `, e.target.value)
}
return (
<>
{fields.map((x) => <Component onChange={handleChange(x)} />}
</>
)
But in this case, it is kind of impossible to memoize the outer and inner lambdas while keeping the entire context in the function with a React.useCallback()
hook.但是在这种情况下,在使用
React.useCallback()
钩子将整个上下文保留在函数中的同时React.useCallback()
外部和内部 lambdas 是不可能的。
In most cases, I have control on the component and change the callback to include the wanted data, but often it happens that the component is from a library (ig Material-UI) and, therefore, cannot be modified.在大多数情况下,我可以控制组件并更改回调以包含所需的数据,但通常会发生组件来自库(ig Material-UI),因此无法修改。
In what way could this callback be entirely memoized with React Hooks? React Hooks 可以通过什么方式完全记住这个回调?
You can generate event handlers for each elements, and memoized the array of event handlers.您可以为每个元素生成事件处理程序,并记住事件处理程序数组。 When create the elements, take the relevant event handler by it's index:
创建元素时,通过它的索引获取相关的事件处理程序:
const { memo, useMemo } = React const Demo = ({ fields }) => { const handlers = useMemo(() => fields.map(fieldName => e => { console.log(`${fieldName}: `, e.target.value) }) , [fields]) return ( <div> { fields.map( (fieldName, i) => ( <input key={fieldName} onChange={handlers[i]} /> )) } </div> ) } const fields = ['field1', 'field2', 'field3'] ReactDOM.render( <Demo fields={fields} />, root )
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root"></div>
How i would handle this is by creating a state
and passing it as a dependency to the useCallback
hook like:我将如何处理这个问题是通过创建一个
state
并将其作为依赖项传递给useCallback
钩子,例如:
const [fields, setFields] = useState({'field1': "", 'field2': "", 'field3': ""});
const handleChange = React.useCallback((e) => {
console.log(`${fieldName}: `, e.target.value);
if(e.target.id === "field1") {
let newFields = {...fields};
fields.field1 = e.target.value;
setFields(newFields);
}
}, [fields])
return (
<>
{fields.map((x) => <Component onChange={handleChange(x)} />}
</>
)
Hope this works for you.希望这对你有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.