brh55 / react-native-masonry

:raised_hands: A pure JS react-native component to render a masonry~ish layout for images with support for dynamic columns, progressive image loading, device rotation, on-press handlers, and headers/captions.
MIT License
1.32k stars 157 forks source link

Updating datas doesn't work #78

Closed QQizi closed 6 years ago

QQizi commented 6 years ago

I couldn't find a way to update the data (bricks). Even if i empty the bricks array nothing changes.

When the state is changed i sometimes encounter this message :

Encountered two children with the same key

Even tho the data doesn't contain any child with the same key

vvavepacket commented 6 years ago

i think updating data on runtime is not supported.

brh55 commented 6 years ago

@QQizi
This should be working again as of v0.4.5. The only exception is when the data.length is the same and it contains the same brick.uri for each element, then it is disregarded.

QQizi commented 6 years ago

@brh55 just installed 0.4.6, still doesn't work. My component :

<Masonry
 sorted
 columns={2}
 imageContainerStyle={{borderRadius:3}}
 bricks={this.state.trendingGifs}
/>

When i set trendingGifs to [] or even when i change the data inside, the first elements which was in trendingGifs stay.

brh55 commented 6 years ago

@QQizi

There shouldn't be any problems with the component itself as it's doing a comparison against prop changes, which should occur during every state change.

Can you provide entire code of parent component?

QQizi commented 6 years ago

Here's basicly what i do. I'm using this plugin to display GIPHY GIF. I have a text input to search for new GIF and display them into the masonry but the first one displayed (the trending GIF) do not disapear.

In this example i just use a press event to empty the bricks array, but nothing change

class Chat extends React.Component {

   state = {
        trendingGifs : []
    };

    componentWillMount(){
        Axios.get('https://api.giphy.com/v1/gifs/trending?api_key=MY_KEY&limit=5')
            .then( (response) => {
                var gifs = [];
                _.map(response.data.data, (gif, key) =>{
                    gifs.push({
                        uri : gif.images.preview_gif.url,
                        key : key,
                        onPress : this._clickGif,
                        data : key
                    })
                });
                this.setState({
                    trendingGifs: gifs
                })
            });
    }

    render(){
        return (
        <View>
            <TouchableWithoutFeedback onPress={()=>{
                this.setState({
                    trendingGifs : []
                })
            }}>
                <Text>empty masonry</Text>
            </TouchableWithoutFeedback>
            <Masonry
                sorted
                columns={2}
                imageContainerStyle={{borderRadius:3}}
                bricks={this.state.trendingGifs}
            />
        </View>
        )
    }   

}
QQizi commented 6 years ago

@brh55 i just resolve the issue.

in resolveBricks() at the begining i did :

this.setState({
  _sortedData : []},()=>{
**INSERT ALL THE resolveBricks function**
}); 
vvavepacket commented 6 years ago

Hi,

Can you provide a detailed solution and changes requirer? I was encountering the same scenario. Thank you

On Wed, Mar 21, 2018, 11:33 QQizi notifications@github.com wrote:

@brh55 https://github.com/brh55 i just resolve the issue.

in resolveBricks() at the begining i did :

this.setState({ _sortedData : []},()=>{ INSERT ALL THE resolveBricks function });

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/brh55/react-native-masonry/issues/78#issuecomment-374981142, or mute the thread https://github.com/notifications/unsubscribe-auth/AH6U2jkxnERkEFMKnPtibfkQ13cou8nDks5tgnLOgaJpZM4SaaAu .

QQizi commented 6 years ago

@vvavepacket just created a pull request : https://github.com/brh55/react-native-masonry/pull/82

brh55 commented 6 years ago

@QQizi Curren PR quickly solves the problem, but it removes any of the optimization logic for pre-existing data. However, after some investigation I realize that we don't have a case of handling empty arrays, hence why it wasn't clearing the array.

I'll provide you with the minor fix in the PR, and if you can re-pull that would be greatly appreciated!

Some side notes: I would recommend moving your api calls into componentDidMount, this article will explain why it's a preferred area for async calls:

https://daveceddia.com/where-fetch-data-componentwillmount-vs-componentdidmount/

In addition, a more performant way to handle button presses is to create your function within your class and assign it to the button. This prevents new functions being created during component renders 👍 .

  removeGifs = () => this.setState({ trendingGifs: [] })
  render() {
    return (
      <TouchableHighlight onPress={this.removeGifs}>
         <Text>Remove Gifs</Text>
     </TouchableHighlight>
    );
}
QQizi commented 6 years ago

@brh55 Thx for your advice i’ll look at it !

My problem doesn’t appear only with an empty array. Even when I load new gifs and send a brand new array, the output is the old ones AND the new ones