【问题标题】:How to avoid inline functions in React/Redux如何避免 React/Redux 中的内联函数
【发布时间】:2019-06-13 03:09:23
【问题描述】:

我遵循 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)}

不立即执行。

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

【问题讨论】:

    标签: reactjs redux


    【解决方案1】:

    性能问题不在于使用箭头函数,而在于在每次渲染时创建新的箭头函数。在您的情况下,您可以使用 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));
    

    【讨论】:

    • 我的操作删除体验,你不会在任何地方使用它,所以当我点击删除时没有任何反应:)。
    • @dragon 我在这里使用它:const del = useCallback(() =&gt; deleteExperience(exp._id), [exp._id]);
    • @dragon 等一下。您有两件东西都命名为deleteExperience,一件是您导入的,另一件是道具?已编辑答案以使用另一个答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 2011-03-05
    • 1970-01-01
    • 2018-01-05
    • 2013-04-20
    相关资源
    最近更新 更多