将数据从孩子传递给父母React Hooks

时间:2019-10-17 20:40:50

标签: javascript reactjs callback react-hooks

我是新来对Hooks做出反应的人(我应该说:甚至还没有开始),但是在这个小问题上我需要帮助。该组件可渲染星星,并允许用户选择等级。我想将{starSelected}值从此组件传递到父组件。

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>
  );
};

我将不胜感激!

父组件


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>
        );
    }
}

2 个答案:

答案 0 :(得分:4)

这可以通过将功能从父组件传递到子组件中,然后调用该函数以更新父组件中的状态来完成。如果需要,您也可以使用此方法完全管理父级中的状态,但是本示例不这样做。

父组件:

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}
    />
  );
}

然后是星标部分:

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>
  );
};

通过将功能从父级传递到子级,然后在子级中调用它,可以更新父级中的状态。

就像我说的那样,您也可以使用它来完全处理状态,然后可以这样编写StarRating:

<StarRating
  totalStars={10}
  onStarUpdate={updateStars}
  selectedStar={selectedStar}
/>

答案 1 :(得分:0)

您只是无法将道具传递给父组件。

您将需要使用外部状态called Redux

这是一个HOC组件,它将位于所有其他组件之上。

您可能需要一些扑热息痛才能阅读文档...