Zorgg Zorgg - 2 months ago 11
Javascript Question

react loop update sate

I'm new to react and what I'm doing is loop to get to show the each element form the props and I want form the picture component update that props, I try to find a way to do it but I didn't know how to do it.
Code for the loop is this:

const pictureItems = this.props.imgFiles.map((img, index) => {
return <picture key={index} imgFile={img} pictureDataUpdate={this.onUpdatPicture} />;
});


The question is how can I update the props that are been pass to the picture component? (I'm already passing the information from picture to the component that is looping). I have so far this.

onUpdatPicture(data) {
console.log(data);
// this.setState(data);
}

Answer

The simplest method for manipulating props sent to a child component would be to store the data in the parent component's state. Doing so would allow you to manipulate the data and send the updated version to your child component.

Assuming our parent component is sent an array of image urls as the images prop, we'll need two main pieces in our code: our update function for our child to call and to map over our images and create our children.

class Gallery extends React.Component {

    constructor(props) {

        super(props)

        //Setting our props to the state of the parent allows us to manipulate the data before sending it back to our child.

        this.state = {
            images: this.props.images || []
        }

    }

    update = (key, value) => {

        // Our update function is sent the {key} of our image to update, and the new {value} we want this key to hold.

        // After we are passed our data, we can simply map over our array and return the new array to our state.

        this.setState({
            images: this.state.images.map( (img, i) => i === key ? value : img)
        })

    };

    render() {

        return (

            <div className="gallery">  // Since we are going to have multiple children, we need to have a wrapper div so we don't get errors.

                {

                    // We map over our data and send our child the needed props.

                    // We send our child the {src} of our image, our {update} function, the id our child will use to update our parent, and a key for React to keep track of our child components

                    images.map( (img, i) => <Picture src={img} update={this.update} id={i} key={'picture_' + i} />)

                }

            </div>

        )

    }

}

After we have our update function setup and our parent is mapping over our images to create the child component, all that's left to do is setup our child component to handle our data.

class Picture extends React.Component {

    render() {

        return (

            // Notice our onClick is an arrow function that calls our update method.  This is so we only call our update function once the onClick is fired, not when the component is being rendered.

            <div className="picture" onClick={() => this.props.update(this.props.id, 'https://static.pexels.com/photos/189463/pexels-photo-189463.png')}>

                <img src={this.props.src} />

            </div>

        )

    }

}

Given the above code, once we render our gallery component, anytime an image is clicked, the child's image is replaced with a new image.

Here is a link to a working example on CodePen.