创建用于在通过.map
函数创建的组件中使用的备注回调的正确方法是什么?
即。这是我要实现的非存储版本:
import * as React from "react";
import { render } from "react-dom";
const NUM_BUTTONS = 5;
function App() {
const [value, setValue] = React.useState(0);
return (
<div className="App">
<h1>Value is : {value}</h1>
{new Array(NUM_BUTTONS).fill(true).map((v, i) => (
<button key={i} onClick={() => setValue(i)}>
{i}
</button>
))}
</div>
);
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);
足够简单。
现在的问题是-我具有内联函数,它将在每次渲染该<button>
组件时重新渲染这些组件。
我想到的一种方法是创建一个已记忆的回调列表,并映射它们:
function App() {
const [value, setValue] = React.useState(0);
const callBacks = new Array(NUM_BUTTONS).fill(true).map((v, i) => {
return React.useCallback(() => setValue(i), []);
});
return (
<div className="App">
<h1>Value is : {value}</h1>
{callBacks.map((v, i) => (
<button key={i} onClick={v}>
i
</button>
))}
</div>
);
}
但是,当然-这会破坏Rules of Hooks之一,您不能从函数或条件内部调用钩子。奇怪的是,此代码仍然有效。
我可以选择的另一种方法是创建一个单独的<SetValueButton>
组件,该组件具有绑定的值,如下所示:
function SetValueButton(props) {
const { value, onClick } = props;
const handleClick = React.useCallback(() => onClick(value), [onClick, value]);
return <button onClick={handleClick}>{value}</button>;
}
function App() {
const [value, setValue] = React.useState(0);
const setValueCb = React.useCallback(i => setValue(i), []);
return (
<div className="App">
<h1>Value is : {value}</h1>
{new Array(NUM_BUTTONS).fill(true).map((v, i) => (
<SetValueButton key = {i} onClick={setValueCb} value={i} />
))}
</div>
);
}
这是正确的主意,还是有更简单的方法来做到这一点?
答案 0 :(得分:2)
避免在此处使用内联箭头功能而不创建多个功能的最佳方法是使用data-attribute
import * as React from "react";
import { render } from "react-dom";
const NUM_BUTTONS = 5;
function App() {
const [value, setValue] = React.useState(0);
const handleClick = React.useCallback((event) => {
const id = event.target.getAttribute('data-index');
setValue(id);
}, [])
return (
<div className="App">
<h1>Value is : {value}</h1>
{new Array(NUM_BUTTONS).fill(true).map((v, i) => (
<button key={i} data-index={i} onClick={handleClick}>
{i}
</button>
))}
</div>
);
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);