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

时间:2019-06-13 03:09:23

标签: reactjs redux

我遵循了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 个答案:

答案 0 :(得分:4)

性能问题并非来自使用箭头功能,而是来自在每个渲染器上创建新的箭头。您可以使用useCallback()来记住它们。 (您需要提取一个组件来呈现每个exp对象,以免破坏the rules of 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));