parent 的 setState 不会触发 child 的 componentWillReceiveProps

setState of parent does not fire componentWillReceiveProps of child

我有一个组件 parent 和一个组件 child,其中一些道具连接到 parent 状态。

在 parent 中我调用了 setState 但 child 的 componentWillReceiveProps 函数没有触发。
更准确地说,它在 parent 的某个点被触发,而在另一个点没有被触发。

这是parent:

... imports

class HomeScreen extends Component {

    constructor(props) {
        super(props);

        dispatchFbPermissionAction = this.dispatchFbPermissionAction.bind(this);

        this.state = {
            fbPermissions: [],
        }
    }

    componentDidMount () {
        this._loadInitialState();
    }

    _responsePermissionsCallback(error: ?Object, result: ?Object) {
        if (error) {
            log('Error fetching data: ' + error.toString());
        } else {
            dispatchFbPermissionAction(result.data);
        }
    }

    dispatchFbPermissionAction = (data) => {
        // **NOT FIRED**
        this.setState({
            fbPermissions: data
        });

        this.props.fbPermissionsLoaded(data);
    }

    async _loadInitialState() {
        AccessToken.getCurrentAccessToken().then(
            (data) => {
                if (data) {
                    const infoRequest = new GraphRequest(
                      '/me/permissions',
                      null,
                      this._responsePermissionsCallback,
                    );
                    new GraphRequestManager().addRequest(infoRequest).start();

                    // **FIRED**
                    this.setState({
                        ...
                    });

                    this.props.loggedIn();
                }
            }
        );
    }

    render () {
        const { navigation } = this.props;

        return (
            <Container>
                <ScrollableTabView
                    <View tabLabel="ios-film" style={styles.tabView}>
                        <Text style={styles.tabTitle}>{_.toUpper(strings("main.theatres"))}</Text>
                        <ListTheatre navigation={this.props.navigation} filterText={this.state.filterText} isLoggedIn={this.state.isLoggedIn} fbPermissions={this.state.fbPermissions}></ListTheatre>
                    </View>
                </ScrollableTabView>
            </Container>
        )
    }
}

const mapStateToProps = (state) => {
    return {
        isLoggedIn: state.isLoggedIn,
        listTheatre: state.listTheatre,
        listMusic: state.listMusic
    };
};

// wraps dispatch to create nicer functions to call within our component
const mapDispatchToProps = (dispatch) => ({
    startup: () => dispatch(StartupActions.startup()),
    loggedIn: () => dispatch({
        type: LOGGED_IN
    }),
    fbPermissionsLoaded: (data) => dispatch({
        type: FB_PERMISSIONS_LOADED,
        fbPermissions: data
    })
});

export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen)

这是 child:

... imports

class ListTheatre extends Component {

    constructor(props) {
        super(props);

        this.state = {
            ...
        }
    }

    componentWillReceiveProps(nextProps) {
        log(this.props)
    }

    shouldComponentUpdate(nextProps, nextState) {
        return !nextState.fetching;
    }

    render() {
        const { navigate } = this.props.navigation;

        return (
            <SectionList
                ...
            />
        )
    }
}

ListTheatre.propTypes = {
    isLoggedIn: PropTypes.bool.isRequired,
}

const mapStateToProps = (state) => {
    return {
        isLoggedIn: state.isLoggedIn
    };
};

const mapDispatchToProps = (dispatch) => ({
    startup: () => dispatch(StartupActions.startup())
});

export default connect(mapStateToProps, mapDispatchToProps)(ListTheatre);

我不明白为什么 GraphRequestManager().addRequest 调用后的 setState 工作得很好(child 的 componentWillReceiveProps 函数被触发),而 dispatchFbPermissionAction 函数中的 setState 没有触发 componentWillReceiveProps child.

函数

这是由于 connect/Connect(ListTheatre) 包装了您的 ListTheatre 组件实现的 sCU(shouldComponentUpdate) 内部 为您关闭它,通过设置 pure 将其关闭连接到 false like

的选项

export default connect(mapStateToProps, mapDispatchToProps, null, {pure: false})(ListTheatre)

[pure] (Boolean): If true, connect() will avoid re-renders and calls to mapStateToProps, mapDispatchToProps, and mergeProps if the relevant state/props objects remain equal based on their respective equality checks. Assumes that the wrapped component is a “pure” component and does not rely on any input or state other than its props and the selected Redux store’s state. Default value: true