2

我正在学习 React,我发现 React.memo() “不起作用”,因为我的组件在我对基于父类的组件所做的每次更新时都会重新渲染。但问题是组件上的道具不会改变,至少对我来说是有意义的

我使用 useEffect 钩子在重新渲染的屏幕上打印,尽管我使用 React.memo(Men)

const Men = props => {
        useEffect(() => {
          console.log("rendered");
        });
        return <p onClick={props.add}>{props.adder}</p>;
    };
    React.memo(Men);

    class App extends React.Component {
        state = {
          counter: 0,
          adder: "press"
        };

        add = () => {
          this.setState(prevState => {
            return {
              counter: prevState.counter + 1
            };
          });
        };

        render() {
          return (
            <div className="App">
              <p>{this.state.counter}</p>
              <Men adder={this.state.adder} add={this.add} />
            </div>
          );
        }
      }

我希望在我的控制台中,useEffect 挂钩内的“渲染”消息只出现一次。

4

2 回答 2

1

React hooks 也有一个依赖数组,没有它 useEffect hook 将在每次渲染时触发它的效果。 反应钩子参考

useEffect(() => {
  console.log("rendered");
});  // every render

useEffect(() => {
  console.log("rendered");
}, []);  // on mount, once

useEffect(() => {
  console.log("rendered");
}, [propValue]);  // every time propValue is a new reference

HOC 函数还可以采用memo相等比较函数来进一步测试何时应该发生重新渲染,但请注意,react 仍然控制它们何时发生。HOC(高阶组件)包装一个组件并返回一个要渲染的新组件。您包装您的组件,但不保存返回的值以供以后渲染。

const MemoizedComponent = React.memo(Component, [optional prop compare function]);
...
render() {
  return (
    <MemoizedComponent />
  );
};
于 2019-07-31T23:16:58.517 回答
1

这是由于您的使用方式而发生的memo- 您需要使用React.memo(Men)为您提供的返回值。

像这样:

此 CodePen导致重新渲染

此 CodePen不会导致重新渲染

正确的:

const MenBefore = props => {
  React.useEffect(() => {
    console.log("rendered");
  });
  return <p onClick={props.add}>{props.adder}</p>;
};
////////////////////////////////////////
const Men = React.memo(MenBefore); // <--- THIS LINE
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

class App extends React.Component {
  state = {
    counter: 0,
    adder: "Click Me - I will -NOT- cause a re-render"
  };

  add = _ => {
    this.setState(prevState => {
      return {
        counter: prevState.counter + 1
      };
    });
  };

  render() {
    return (
      <div className="App">
        <p>{this.state.counter}</p>
        <Men adder={this.state.adder} add={this.add} />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.body);

不正确:

const Men = props => {
  React.useEffect(() => {
    console.log("rendered");
  });
  return <p onClick={props.add}>{props.adder}</p>;
};
/////////////////////////////
React.memo(Men); // <<<--------- WRONG
// ^^^^^^^^^^^^^^^^^^^^^^^^^^

class App extends React.Component {
  state = {
    counter: 0,
    adder: "Click Me - I will cause a re-render"
  };

  add = _ => {
    this.setState(prevState => {
      return {
        counter: prevState.counter + 1
      };
    });
  };

  render() {
    return (
      <div className="App">
        <p>{this.state.counter}</p>
        <Men adder={this.state.adder} add={this.add} />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.body);
于 2019-07-31T23:18:18.003 回答