简体   繁体   中英

How to re-render React Native Component after transferring prop to there

I'm trying to implement a list of users with searching by username possibility.

I've faced with the issue with re-rendering SearchListOfUsers after I change a prop usernameFilter in a parent Component SearchPeopleScreen and pass it to a child SearchListOfUsers .

I know that a component should re-render itself when its state is changed but in my case even state of child component doesn't change. How to update my child comp. SearchListOfUsers after I pass a prop usernameFilter ?

Here is my parent comp. SearchPeopleScreen :

export default class SearchPeopleScreen extends Component {

constructor(props) {
    super(props);
    this.state = {
        ...
        usernameFilter: ''
    }
}

render() {
    return(
        <Container>

            <Header style = {searchPeopleScreenStyle.header} searchBar>
                <Title style = {searchPeopleScreenStyle.title}>
                    Search
                </Title>

                <Right/> 
                <Item style = {searchPeopleScreenStyle.searchFieldWrapper}>
                     <IconSimpleLine name = 'magnifier' color = {placeholder} size = {20} style = {{padding: 10}}/>
                     <TextInput 
                               underlineColorAndroid = 'transparent'
                               onChangeText = {(text) => {
                                  this.setState({usernameFilter: text});
                               }}
                               placeholder = 'Type username'
                               style = {searchPeopleScreenStyle.searchInput}
                                    maxLength = {15}
                       />
                 </Item>

            </Header>

            <Content>
                <ScrollView contentContainerStyle = {searchPeopleScreenStyle.container}>

                    ...

                    {/* Search screen's body */}
                    <SearchListOfUsers searchOption = {this.state.searchOption}
                                        usernameFilter = {this.state.usernameFilter}/>

                </ScrollView>
            </Content>

        </Container>
    )
}
}

And here is my child comp. SearchListOfUsers :

export default class SearchListOfUsers extends Component {

constructor(props) {
    super(props);

    this.state = {
        usersDataArray: [],
        usernameFilter: this.props.usernameFilter
    };

    this.arrayHolder = [];
    console.warn('1 - ' + this.state.usernameFilter)
}

componentDidMount() {
    this.getAllUsersData()

    console.warn(this.state.usernameFilter)

    if(this.state.usernameFilter) {
        this.filterUsers();
    }
}

getAllUsersData = () => {
    return new Promise((resolve, reject) => {
        // getting users data and creating an array 
        ...
        allUsersDataArray.push({...});

        this.setState({
            usersDataArray: allUsersDataArray
        });

        resolve();
    })
}

filterUsers = () => {
    const newUsersDataArray = this.arrayHolder.filter((user) => {
        const usernameInTheList = user.userUsername.toUpperCase();
        const inputtedUsername = this.state.usernameFilter.toUpperCase();
        return usernameInTheList.includes(inputtedUsername);
    });

    this.setState({
        usersDataArray: newUsersDataArray
    })
}

render() {
    return(
          <Content contentContainerStyle = {searchPeopleScreenStyle.listOfUsersWrapperGlobal}>
                <FlatList
                    data = {this.state.usersDataArray}
                    keyExtractor = {(item) => (item.userId)}
                    renderItem = {({item}) => (
                        <UserListItem
                                        country = {item.userCountry}
                                        username = {item.userUsername}
                                        ...
                        />
                    )}
                />
            </Content>
        )
    }
}
}

If you need to filter your data based on selections from a parent component, you should also be filtering your collection there as well. Once you have filtered your collection, that should be passed to the child component.

The child component in this case should be purely presentational and static. It shouldn't care about filtering data or updating it's component state etc, it just wants to render out whatever props it is passed. searchOption, usernameFilter, dataCollection

You filter users in componentDidMount lifecyle method which means it will run only once on mounting process of child component.

You can filter in render method like

filterUsers = () => {
    if(!this.props.usernameFilter.length) return this.state.usersDataArray

    return this.state.usersDataArray.map((user) => {
        const usernameInTheList = user.userUsername.toUpperCase();
        const inputtedUsername = this.props.usernameFilter.toUpperCase();
        return usernameInTheList.includes(inputtedUsername);
    });
}

render() {
    return(
          <Content contentContainerStyle = {searchPeopleScreenStyle.listOfUsersWrapperGlobal}>
                <FlatList
                    data = {this.filterUsers()}
                    keyExtractor = {(item) => (item.userId)}
                    renderItem = {({item}) => (
                        <UserListItem
                                        country = {item.userCountry}
                                        username = {item.userUsername}
                                        ...
                        />
                    )}
                />
            </Content>
        )
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM