简体   繁体   中英

How can I pass a variable between two components in React?

I have a form component in React that I use to send data to a pg database.

This is my form script:

import bodyParser from 'body-parser';
import React, { Fragment, useState } from 'react';
import RatingStar from '../components/rating'

const InputData = () => {
    
    const [name, setName] = useState('')
    const [rating, setRating] = useState('')

    const onSubmitForm = async(e) => {
        e.preventDefault();
        try {
            const payload = {
                name,
                rating
            }

            const response = await fetch("path", {
                method:"POST",
                headers:{"Content-Type":"application/json"},
                body:JSON.stringify(payload)
            });
            window.location = "/";
        } catch (error) {
            console.log(error.message);
        }
    }

    return(
        <Fragment>
            <div className="container">
                <h1 className="text-center mt-5">RATE</h1>
                <form className="mt-5" onSubmit={onSubmitForm}>
                    <div className="form-group">
                        <input 
                            placeholder="Name"
                            type='text' 
                            className='form-control' 
                            value={name} 
                            onChange={e => setName(e.target.value)}
                        />
                    </div>
                    <div className="form-group">
                        <div>
                            <RatingStar
                                value={}
                            />
                        </div>
                    </div>
                    <div className="d-flex justify-content-center">
                        <button type="submit" className="d-flex btn btn-primary">Submit</button>
                    </div>
                </form>
            </div>

        </Fragment>
    );
}

export default InputData;

And this is my rating component:

import React, { useState } from 'react';
import { render } from 'react-dom';
import ReactStars from 'react-rating-stars-component'
import './style.css'


export default function RatingStar() {
  
  const [rating, setRating] = useState("")  

  const secondExample = {
    size: 50,
    count: 5,
    color: "black",
    activeColor: "yellow",
    value: 0,
    a11y: true,
    isHalf: true,
    emptyIcon: <i className="far fa-star" />,
    halfIcon: <i className="fa fa-star-half-alt" />,
    filledIcon: <i className="fa fa-star" />,
    onChange: (newValue) => {
      console.log(`Example 2: new value is ${newValue}`);
      setRating(newValue) // my try
    }
  };
  return (
    <div className="starComponent">
      <ReactStars {...secondExample}
       />
    </div>
  );
}

So I was wondering how I could use newValue in the form component.

For now I tried using useState in the rating component but I can't access it from the form component to use it in my paylod.

Instead of keeping same state (ie rating value) in two components, keep it in form component and pass it as prop to the Rating component.

Rating component will notify the parent(Form) component whenever the value gets changed by calling a function. This is called Lifting state up .

Here is the code for Rating component which gets rating and onRatingChange props from the form component. onRatingChange will be called with newValue from inside onChange function.

export default function RatingStar({ rating, onRatingChange }) {
  const secondExample = {
    size: 50,
    count: 5,
    color: "black",
    activeColor: "yellow",
    value: rating, // pass rating value here
    a11y: true,
    isHalf: true,
    emptyIcon: <i className="far fa-star" />,
    halfIcon: <i className="fa fa-star-half-alt" />,
    filledIcon: <i className="fa fa-star" />,
    onChange: (newValue) => {
      console.log(`Example 2: new value is ${newValue}`);
      // call onRatingChange function with new rating value
      onRatingChange(newValue);
    }
  };
  return (
    <div className="starComponent">
      <ReactStars {...secondExample} />
    </div>
  );
}   

This is the code for Form component.

const InputData = () => {
    const [name, setName] = useState('')
    const [rating, setRating] = useState(0)

    const onSubmitForm = async(e) => {
        e.preventDefault();
        try {
            const payload = {
                name,
                rating
            }

            const response = await fetch("path", {
                method:"POST",
                headers:{"Content-Type":"application/json"},
                body:JSON.stringify(payload)
            });
            window.location = "/";
        } catch (error) {
            console.log(error.message);
        }
    }

    return(
        <Fragment>
            <div className="container">
                <h1 className="text-center mt-5">RATE</h1>
                <form className="mt-5" onSubmit={onSubmitForm}>
                    <div className="form-group">
                        <input 
                            placeholder="Name"
                            type='text' 
                            className='form-control' 
                            value={name} 
                            onChange={e => setName(e.target.value)}
                        />
                    </div>
                    <div className="form-group">
                        <div>
                            <RatingStar
                                rating={rating}
                                onRatingChange={(newRating)=>{
                                  // update rating value here when you get a new value
                                  setRating(newRating);
                                }}
                            />
                        </div>
                    </div>
                    <div className="d-flex justify-content-center">
                        <button type="submit" className="d-flex btn btn-primary">Submit</button>
                    </div>
                </form>
            </div>

        </Fragment>
    );
}

export default InputData;

You need to keep the state in InputData and pass it into RatingStar with the change handler.

const InputData = () => {
  const [rating, setRating] = useState(0);
  const handleRatingChange = (newRating) => {
    console.log(`setting rating to ${newRating}`);
    setRating(newRating);
  }

  return (
    <RatingStar value={rating} onChange={handleRatingChange} />
  );
};

Then RatingStar just uses the values from its parent.

const RatingStar = ({ value, onChange }) => {
  const otherProps = {};
  return (
    <ReactStars {...otherProps} value={value} onChange={onChange} />
  );
};

Here, RatingStar is a controlled component

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM