首页 > 解决方案 > React component not re-rendering when props change

问题描述

I just had a bug report come through for my app where undefined undefined is printing to the user's screen, where they should see a first and last name. Thinking through why this would be the case, I know the value is always available in the database. So therefore I assume that the issue is that, in a rare situation, the screen might load before all the data is available. I am using ? to handle null checks to avoid errors, but technically this could result in the page loading before the data is available.

My question is twofold, based on the code I'm about to share, will react automatically re-render the screen when the values do arrive if they weren't available on first page load? And, if not, what is a better way to handle that scenario?

Here is my relevant code:

import React from 'react';
import {
  Text,
  View,
  Image,
} from 'react-native';

import moment from "moment";
import componentStyles from './styles';

import { statusCodeToIcon, statusCodeToText, visitTypeToText } from '../../lib/VisitUtils';

export class VisitItem extends React.PureComponent {
  render() {
    const { item, screenType } = this.props;

    return (
      <View style={componentStyles.sectionContainer}>
        <View style={componentStyles.visitItemContainer}>
          <Image
            style={componentStyles.visitIcon}
            source={statusCodeToIcon(item?.status?.value)}
          />
          
          <View style={componentStyles.flexColumn}>
            <Text style={componentStyles.largeText}>{visitTypeToText(item?.type?.value)}</Text>
            { 
              screenType && screenType === 'detailsReview' ?
              <Text style={componentStyles.mediumText}>
                {`${item?.name?.first?.value} ${item?.name?.last?.value}`}
              </Text> : null
            }
            <Text style={componentStyles.mediumText}>{statusCodeToText(item?.status?.value)}</Text>
            <Text style={componentStyles.mediumText}>{moment(item?.date?.value).format('MMM Do YYYY')}</Text>
          </View>
        </View>
        <View style={componentStyles.horizontalBorderLight} />
      </View>
    );
  }
}
 

标签: reactjsreact-native

解决方案


According to React docs on pure components:

React.PureComponent is similar to React.Component. The difference between them is that React.Component doesn’t implement shouldComponentUpdate(), but React.PureComponent implements it with a shallow prop and state comparison.

React.PureComponent’s shouldComponentUpdate() only shallowly compares the objects. If these contain complex data structures, it may produce false-negatives for deeper differences. Only extend PureComponent when you expect to have simple props and state, or use forceUpdate() when you know deep data structures have changed. Or, consider using immutable objects to facilitate fast comparisons of nested data.

Furthermore, React.PureComponent’s shouldComponentUpdate() skips prop updates for the whole component subtree. Make sure all the children components are also “pure”.

Given that your prop changes are deep, pure components shallow comparison doesn't seem to detect the changes and rerender.

Try extending React.Component instead.


推荐阅读