Задать вопрос

Return: React Component: будет ли утечка памяти?

Хочу в классе, который отвечает за взаимодействие с API отлавливать все ошибки, чтобы не ловить их в каждом компоненте, вызывающем методы этого класса. Проблема: класс не связан с React и Redux. Просто класс со статическими методами. А вот обработчик ошибок должен иметь возможность диспатчить экшены в стор.

Думаю реализовать примерно так (код пишу на коленке, он скорее всего не рабочий, просто иллюстрация идеи):
const ErrorsHandler(error) => {
const mapDispatchToProps = dispatch => ({
    newError: () => {
            dispatch( { type: 'NEW_ERROR' } );
    }
}); 
const DispatcherErrors = (props) => {
props.newError();
return null;
}

// Вернуть функцию-компонент, подключенный к стору
 return connect(null, mapDispatchToProps)(DispatcherErrors)
}


// POST-запрос, ошибка передается в обработчик
 API.post('auth', { login, pass })
.then(
  res => res,
 err => ErrorsHandler(err)
)


Общее описание идеи: обернуть react-компонент, подключенный к стору в функцию, эту функцию вызывать, передавая ошибку в нее.

Все бы ничего, но из-за недостаточного понимания работы react-redux, я не уверен в том, что не будет утечки памяти. Функция DispatcherErrors передается в connect и, возможно, на нее останется ссылка где-то в недрах react-redux. Тогда, вызывая каждый раз функцию, я буду создавать новые компоненты, а старые удаляться не будут.
  • Вопрос задан
  • 407 просмотров
Подписаться 1 Средний Комментировать
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
Frontend Developer
Бесполезный велосипед изобретаете.

Вариант 1. Если используете redux-thunk:
export const handleError = error => ({ type: 'NEW_ERROR', payload: error });
export const doSomething = data => ({ type: 'DO_SOMETHING', payload: data });

import { apiCall } from './api';
import { handleError, doSomething } from './actionCreators';

export const asyncAction = () => dispatch => {
  try {
    const result = await apiCall();
    dispatch(doSomething(result));
    
    return result;
  } catch (e) {
    dispatch(hanldeError(e));
  }
};

аналогичным образом можно использовать блок catch если используете redux-saga.
Если еще не используете, одно из этих middleware, то рекомендую скорей познакомиться с ними и начать использовать.

Вариант 2. Если не используете:
export const handleError = error => ({ type: 'NEW_ERROR', payload: error });
export const doSomething = data => ({ type: 'DO_SOMETHING', payload: data });

import { connect } from 'react-redux';
import { apiCall } from './api';
import { handleError, doSomething } from './actionCreators';

class ExampleComponent extends React.Component {
  componentDidMount() {
    const { dispatch } = this.props;

    apiCall().then(
      res => dispatch(doSomething(res)),
      err => dispatch(handleError(err)),
    );
  }
  
  render() { /* ... */ }
}

export default connect()(ExampleComponent);

или:
import { connect } from 'react-redux';
import { apiCall } from './api';
import { handleError, doSomething } from './actionCreators';

class ExampleComponent extends React.Component {
  componentDidMount() {
    const { doSomething, handleError } = this.props;

    apiCall().then(
      res => doSomething(res),
      err => handleError(err),
    );
  }
  
  render() { /* ... */ }
}

mapDispatchToProps = {
  handleError,
  doSomething,
};

export default connect(null, mapDispatchToProps)(ExampleComponent);


Вообще, самый простой способ сделать dispatch в store это:
store.dispatch(someAction());

Прежде чем начнете изобретать очередной велосипед, настоятельно рекомендую хорошо изучить документацию react, redux и react-redux.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы