Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing Data from Child to Parents React Hooks [duplicate]

I am new to react Hooks (I should say: haven't even started with them yet), but I need assistance with this small problem. This component renders stars and allows a user to select the rating. I want to pass the {starSelected} value from this component to a parent component.

import React, { useState } from "react";
import "./styles.css";

const Star = ({ selected = false, onClick = f => f }) => (
  <div className={selected ? "star selected" : "star"} onClick={onClick} />
);

const StarRating = ({ totalStars }) => {
  const [starsSelected, selectStar] = useState(0);
  return (
    <div className="star-rating">
      {[...Array(totalStars)].map((n, i) => (
        <Star
          key={i}
          selected={i < starsSelected}
          onClick={() => selectStar(i + 1)}
        />
      ))}
      <p>
        {starsSelected} of {totalStars} stars
      </p>
    </div>
  );
};

I would appreciate any help!!!

Parent Component


class RatingNFeedback extends Component {
    constructor(props) {
        super(props);
        this.state = {
            user: {},
            modal: false,
            ratings: '',
            feedback: '',
            feedbackTitle: '',
            errors: {}
        };
        this.toggle = this.toggle.bind(this);
    }

    toggle() {
        this.setState(prevState => ({
            modal: !prevState.modal,
            ratings: '',
            feedback: '',
            feedbackTitle: ''
        }));
    }

    handleRating = (assetId, accessToken) => {
        const {rating, feedback, feedbackTitle} = this.state;
        const ratings = {
            rating,
            feedbackTitle,
            feedback,
            asset: assetId
        };
        this.props.addRatingNComment(ratings, accessToken);
        this.toggle();
    };

    onChange = e => {
        this.setState({
            [e.target.name]: e.target.value
        });
    };

    isModalOpen() {
        return this.state.modal;
    }

    render() {
        const {ratingCount, commentCount, assetId, accessToken} = this.props;
        let stars = [];
        //loop 5 times for stars
        for (let i = 1; i <= 5; i++) {
            let path = require('../../assets/rateFull.svg');
            if (i > ratingCount) {
                path = require('../../assets/RateZero.svg');
            }
            stars.push(<img src={path} alt="" className="card-category-rating" />);
        }
        let userpic = defaultPic;
        if (this.props.user) {
            userpic =
                'http://people.com/User%20Photos/Profile%20Pictures/' +
                this.props.user.profile +
                '_LThumb.jpg';
        }

        return (
            <React.Fragment>

                <Modal
                    isOpen={this.isModalOpen()}
                    toggle={this.toggle}
                    //style={{height: '500px', width: '500px'}}
                    centered
                    className="modal"
                    animation="true"
                >
                    <ModalHeader toggle={this.toggle} className="modal-header">
                        <span className="modal-title"> How would you rate this report? </span>
                    </ModalHeader>
                    <ModalBody className="modal-body ">
                        <div className="rating-modal-header">
                            {' '}
                            <div className=" image-name-box">
                                <div className="circular-landscape image-box">
                                    <img src={userpic} alt="Employee Image" className="user-profile" />{' '}
                                </div>
                                <div className="name-box">
                                    {' '}
                                    <p className="normal-text-2">
                                        {' '}
                                        {`${this.props.userName} ${this.props.familyName}`}{' '}
                                    </p>{' '}
                                    <p className="small-text-2 "> Your review will be posted on Our Website.</p>
                                </div>
                            </div>{' '}
                        </div>
                        <div className="heading3">Your Ratings</div>

                        <StarRating totalStars={5} />

                        <FormTextInput
                            label="Your Feedback:"
                            name="feedbackTitle"
                            value={this.state.feedbackTitle}
                            onChange={this.onChange}
                            placeholder="Title goes here..."
                            type="text"
                        />
                        <FormTextInput
                            //label="Your Feedback:"
                            name="feedback"
                            value={this.state.feedback}
                            onChange={this.onChange}
                            placeholder="Write your feedback here..."
                            type="textarea"
                        />
                    </ModalBody>
                    <ModalFooter>
                        <Button
                            color="primary"
                            onClick={() => this.handleRating(this.props.assetId, this.props.accessToken)}
                        >
                            Submit
                        </Button>{' '}
                        <Button color="secondary" onClick={this.toggle}>
                            Cancel
                        </Button>
                    </ModalFooter>
                </Modal>
            </React.Fragment>
        );
    }
}
like image 980
Ada_lovelace Avatar asked Oct 17 '19 20:10

Ada_lovelace


People also ask

How do you pass data from child to parent in React using hooks?

First, you'll need to create two components, one parent and one child. Next, you'll import the child component in the parent component and return it. Then you'll create a function and a button to trigger that function. Also, you'll create a state using the useState Hook to manage the data.

How many ways to pass data from child to parent in React?

In other words, data flows only one way, from the parent to the child component, in the case of React. The reverse of that, i.e. passing data from the child to the parent is not possible, at least not in theory. Data can be passed from the parent to the child component via props.

Can we pass data from child to parent in React?

To pass data from child to parent component in React: Pass a function as a prop to the Child component. Call the function in the Child component and pass the data as arguments. Access the data in the function in the Parent .

How do I pass data from grandchild to parents in React?

What you should do is: On the parent you have [state, setState] On the current component pass setStat as a prop to child component and then from child component pass setState as a prop to grandchild component. Then on grandchild component you can do something like: props. setState(array).


1 Answers

This can be done by passing a function from the parent component into the child component and then calling that to update the state in the parent. You could also use this method to completely manage the state in the parent if you wanted to, but this example doesn't do that.

Parent component:

import React, { useState } from "react";
import "./styles.css";

const ParentComponent = () => {
  const [selectedStar, setSelectedStar] = useState();

  const updateStars = (star) => {
    setSelectedStar(star);
  }

  return (
    <StarRating
      totalStars={10}
      onStarUpdate={updateStars}
    />
  );
}

Then the star component:

import React, { useState } from "react";
import "./styles.css";

const Star = ({ selected = false, onClick = f => f }) => (
  <div className={selected ? "star selected" : "star"} onClick={onClick} />
);

const StarRating = ({ totalStars, onStarUpdate }) => {
  // you should call your 'setter' `set` and then the name of the const
  // rather than 'selectStar'
  const [starsSelected, setStarsSelected] = useState(0);

  const handleOnClick = (index) => {
    setStarsSelected(index + 1);
    // this next line will update the state in the parent component
    onStarUpdate(index + 1);
  }

  return (
    <div className="star-rating">
      {[...Array(totalStars)].map((n, i) => (
        <Star
          key={i}
          selected={i < starsSelected}
          onClick={() => handleOnClick(i)}
        />
      ))}
      <p>
        {starsSelected} of {totalStars} stars
      </p>
    </div>
  );
};

By passing a function from the parent into the child, and then calling it in the child, you can update the state in the parent.

Like I say you could also use this to completely handle the state, then you could write the StarRating like this:

<StarRating
  totalStars={10}
  onStarUpdate={updateStars}
  selectedStar={selectedStar}
/>
like image 147
Brett East Avatar answered Sep 17 '22 17:09

Brett East