Как избежать встроенных функций в React / Redux - PullRequest
1 голос
/ 13 июня 2019

Я следую учебному пособию по 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 Ответ

4 голосов
/ 13 июня 2019

Проблема производительности заключается не в использовании стрелок, а в создании новых при каждом рендере. В вашем случае вы можете использовать useCallback(), чтобы запомнить их. (Вам потребуется извлечь компонент для рендеринга каждого exp объекта, чтобы не нарушать правил хуков .) Что-то вроде этого должно работать:

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));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...