javascriptreactjsreact-nativestates

Change color to icon after asynchronous fetch


I have and vector icon into of a TouchableHighlight. When the TouchableHighlight is pressed, the app will fetch content from an API. After parse the result, the result is saved in a state, state named favorited, is a boolean array, save if the icon was pressed or not.

My idea was save into an boolean array called "favorited" if the ID was favorited or not. So the state of color is this.state.favorited[id]. Maybe was a bad idea set color in that way, hope you give me better ideas :)

The color parameter in vector-icon is

<Ionicons.Button 
    name="ios-star" 
    color={ (this.state.favorited[post.id]) ? 'white' : 'black' }
    backgroundColor="transparent"
    underlayColor="transparent"
    onPress={()=> {
        vote = this.favPost(post);
        } 
    }
/>

So my try was when the icon was pressed, send the data to a API and in the asynchronous response of the fetch, and then update the state this.state.favorited[data.id]

favPost function updates the state 'favorited': val is true or false

favPost(data){
    fetch(..blabla..).
    then(response.json()).
    then({
        ...
        var favorited = this.state.favorited;
        favorited[post.id] = val;
        this.setState({'favorited' : favorited});
        ...
    })
}

So I don't know how do make this work. Maybe I can't assign a color using (bool) ? : expression.


react-native --version:

react-native-cli: 2.0.1
react-native: 0.43.3

npm list --depth=0 | grep vector-icon

├── react-native-vector-icons@4.1.1


Solution

  • You are on the right track but there are some mistakes in your code.

    1º You cannot mutate the state directly

    var favorited = this.state.favorited;
    favorited[post.id] = val; // This is wrong
    

    Assuming you are storing the favorited ids in the state like this

    state = {
        favorited : [] // [1,2,3, etc]
    }
    

    you should update your state like this

    favPost(data){
        fetch(..blabla..).
        then(response.json()).
        then({
            ...
            this.setState({favorited: [...this.state.favorited, post.id]});
            ...
        })
    }
    

    2º The condition you are using to check if the button has been clicked or not should be something like this

    color={this.state.favorited.find(v => v === post.id) ? 'white' : 'black' }
    

    Here's a working example of what you are trying to achieve.

    (you just have to remove the modal & click on "Tap to play").