React 16.3 & getDerivedStateFromProps

@, в [JavaScript, Заметки]

На componentWillReceiveProps часто вешаются пачки методов для реагирования на изменение props'ов. С вводом нового API придётся рефакторить методы жизненного цикла компонентов.

Из различий, новый метод должен возвращать объект, которым будет обновлено состояние, или null, если состояние трогать не надо.

Из печального то, что componentWillReceiveProps имеет this, а вот его замена getDerivedStateFromProps - static, поэтому ссылаться полноценно на текущий инстанс не может. Но в большинстве [моих] случаев разница незаметна:

componentWillReceiveProps(nextProps) {
    const {
        instances, activeInstanceName, urls, actions,
        shouldFetchEndpoints, shouldFetchInspections, shouldFetchInstances,
    } = nextProps;

    if (!isEmpty(instances) && !activeInstanceName)
        actions.setActiveInstance(instances[0].name);

    shouldFetchEndpoints && actions.fetchEndpoints(urls.endpoints);
    shouldFetchInstances && actions.fetchInstances(urls.status);
    shouldFetchInspections && actions.fetchInspections(urls.inspections);
}

Стало:

static getDerivedStateFromProps(nextProps) {
    const {
        instances, activeInstanceName, urls, actions,
        shouldFetchEndpoints, shouldFetchInspections, shouldFetchInstances,
    } = nextProps;

    if (!isEmpty(instances) && !activeInstanceName)
        actions.setActiveInstance(instances[0].name);

    shouldFetchEndpoints && actions.fetchEndpoints(urls.endpoints);
    shouldFetchInstances && actions.fetchInstances(urls.status);
    shouldFetchInspections && actions.fetchInspections(urls.inspections);

    return null;
}

Но если старая логика была завязана на this, то придётся засовывать изменяемый объект в state, чтобы было с чем его сравнивать:

componentWillReceiveProps(nextProps) {
    const { routeInstanceName: oldRouteInstanceName } = this.props;    
    const { routeInstanceInfo, routeInstanceName } = nextProps;

    if (isEmpty(routeInstanceInfo) && routeInstanceName !== oldRouteInstanceName)
        this.props.actions.fetchInfo(routeInstanceName);
}

Стало:

static getDerivedStateFromProps(nextProps, prevState) {
    const { actions } = nextProps;

    const { routeInstanceName } = nextProps;
    const { routeInstanceName: prevRouteInstanceName } = prevState;

    if (routeInstanceName !== prevRouteInstanceName) {
        actions.fetchInfo(routeInstanceName);
        return { routeInstanceName };
    }

    return null;
}

Имхо стало лучше, ибо pure stuff понятней и проще тестируется.

night-crawler
Просмотров: 1107
blog comments powered by Disqus