在还使用.map

时间:2019-09-13 05:57:29

标签: reactjs react-hooks

创建用于在通过.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);

(Code Sandbox)

足够简单。

现在的问题是-我具有内联函数,它将在每次渲染该<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>
  );
}

(Code Sandbox)

但是,当然-这会破坏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>
  );
}

(Code Sandbox)

这是正确的主意,还是有更简单的方法来做到这一点?

1 个答案:

答案 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);

Working demo