如何避免 React/Redux 中的内联函数

IT技术 reactjs redux
2021-05-24 14:19:45

我遵循了 React/Redux 教程,从我在互联网上的几篇文章中看到的内容中,我意识到内联函数对 React 的性能不利。

据我所知,函数是引用类型,如果您使用内联函数,对于每次重新渲染,该函数将在内存中占据不同的位置。

在教程示例中,我有这个 deleteExperience() 方法,教师使用内联方法。

import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Moment from 'react-moment';
import { Link, withRouter } from 'react-router-dom';
import { deleteExperience } from '../../actions/profileActions';

const Experience = ({ experience, deleteExperience }) => {
  const experiences = experience.map(exp => (
    <tr key={exp._id}>
      <td>{exp.company}</td>
      <td className="hide-sm">{exp.title}</td>
      <td>
        <Moment format="YYYY/MM/DD">{exp.from}</Moment> -
        {exp.to === null ? (
          ' Now '
        ) : (
          <Moment format="YYYY/MM/DD">{exp.to}</Moment>
        )}
      </td>
      <td>
        <button className="btn btn-danger" onClick={() => deleteExperience(exp._id)}>
          Delete
        </button>
      </td>
    </tr>
  ));

  return (
    <Fragment>
      <h2 className="my-2">Experience Credentials</h2>
      <table className="table">
        <thead>
          <tr>
            <th>Company</th>
            <th className="hide-sm">Title</th>
            <th className="hide-sm">Years</th>
            <th />
          </tr>
        </thead>
        <tbody>{experiences}</tbody>
      </table>
    </Fragment>
  );
};

Experience.propTypes = {
  experience: PropTypes.array.isRequired,
  deleteExperience: PropTypes.func
};


export default connect(
  null,
  {deleteExperience}
)(withRouter(Experience));

所以导师说他用的是内联函数

 onClick={() => deleteExperience(exp._id)}

而不仅仅是直接调用函数

 onClick={deleteExperience(exp._id)}

不立即执行。

所以,请有人告诉我,如果关于使用内联函数的不良做法的理论是正确的,如何处理这种情况?我尝试了很多方法,都没有成功。

1个回答

性能问题不在于使用箭头函数,而在于在每次渲染时创建新的箭头函数。在您的情况下,您可以使用useCallback()来记住它们。(您需要提取一个组件来呈现每个exp对象,以避免违反hooks 规则。)这样的事情应该可以工作:

import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Moment from 'react-moment';
import { Link, withRouter } from 'react-router-dom';
import { deleteExperience } from '../../actions/profileActions';

const Exp = ({ exp, deleteExperience }) => {
  const del = useCallback(() => deleteExperience(exp._id), [deleteExperience, exp._id]);
  return (
    <tr>
      <td>{exp.company}</td>
      <td className="hide-sm">{exp.title}</td>
      <td>
        <Moment format="YYYY/MM/DD">{exp.from}</Moment> -
        {exp.to === null ? (
          ' Now '
        ) : (
          <Moment format="YYYY/MM/DD">{exp.to}</Moment>
        )}
      </td>
      <td>
        <button className="btn btn-danger" onClick={del}>
          Delete
        </button>
      </td>
    </tr>
  );
};

const Experience = ({ experience, deleteExperience }) => {
  const experiences = experience.map(exp => (
    <Exp key={exp._id} exp={exp} deleteExperience={deleteExperience} />
  ));

  return (
    <Fragment>
      <h2 className="my-2">Experience Credentials</h2>
      <table className="table">
        <thead>
          <tr>
            <th>Company</th>
            <th className="hide-sm">Title</th>
            <th className="hide-sm">Years</th>
            <th />
          </tr>
        </thead>
        <tbody>{experiences}</tbody>
      </table>
    </Fragment>
  );
};

Experience.propTypes = {
  experience: PropTypes.array.isRequired,
  deleteExperience: PropTypes.func
};


export default connect(
  null,
  {deleteExperience}
)(withRouter(Experience));