React review form not submitting review on submit

Viewed 119

I just want to preface this that I am learning JavaScript and React so this is all very new to me.

I am building a "simple" movie rating app and need to be able to push a review to a div "on submit" and cannot figure out how to do so. I have tried using update state in react and/or creating functions to try to accomplish this and cannot figure out how to do this for the life of me. I did somewhat succeed using the latter method, but was getting errors about using unique key props. The other problem was I am to use a star-rating component and when I submitted the review, it wasn't pushing that to the div. This is where I'm at currently:

import { Button, Form, Input } from "reactstrap";
import Stars from "./stars";


export default function ReviewForm() {
  const [reviews, setReviews] = useState("");
  const onChange = (e: any) => {
    setReviews(e.target.value);
  };
  const onSubmit = (e: any) => {
    console.log("Form Submitted");
  };
  

  return (
    <div className="form-container">
      <Stars />
      <Form onSubmit={onSubmit}>
        <Input
          className="form-control" type="text"
          placeholder="Enter you review"
          value={reviews}
          onChange={onChange}
        />
        <br></br>
        <Button type="submit" className="btn btn-primary">
          Submit
        </Button>
      </Form>
    </div>
  );
}

// This is what I have in my Stars component:

import React, { useState } from "react";
import { FaStar} from 'react-icons/fa'

const Stars = () => {
    const [rating, setRating] = useState(0);
    const [hover, setHover] = useState(null);
    return(
        <div>
            {[...Array(5)].map((star, i) => {
                const ratingValue = i + 1;
                return <label>
                    <input 
                    type="radio" 
                    name="rating" 
                    value={ratingValue} 
                    onClick={() => setRating(ratingValue)}
                    />
                    <FaStar 
                    className="star" 
                    color={ratingValue <= (hover || rating) ? "gold" : "lightgray"} 
                    size={20}
                    onMouseEnter={() => setHover(ratingValue)}
                    onMouseLeave={() => setHover(null)}
                    />
                    </label>;
            })}
            <p>I rate this movie {rating + " stars"}</p>
        </div>
        );
};

export default Stars```
3 Answers

You probably are seeing a page refresh when you press the submit button. This is the default behavior of HTML forms.

When using React or any front-end framework, you'd want to handle the form submission yourself rather than letting the browser submit your forms.

In your onSubmit function, add the following line e.preventDefult()

const onSubmit = (e: any) => {
  e.preventDefault()
  console.log("Form Submitted");
};

Your code will work perfectly.

import { Button, Form, Input } from "reactstrap";
import Stars from "./stars";


export default function ReviewForm() {
  const [Reviews, setReviews] = useState("");
const [ReviewsRating, setReviewsRating] = useState(5);
const [Reviews_, setReviews_] = useState([]);
  const onChange = (e: any) => {
    setReviews(e.target.value);
  };
  const onSubmit = (e: any) => {
    e.preventDefault()
console.log("Form Submitted");
//After upload to the server
setReviews_([Reviews, ...Reviews_]
  };
  

  return (
    <div className="form-container">
      <Stars getRating={getRating}/>
      <Form onSubmit={onSubmit}>
        <Input
          className="form-control" type="text"
          placeholder="Enter you review"
          value={reviews}
          onChange={onChange}
        />
        <br></br>
        <Button type="submit" className="btn btn-primary">
          Submit
        </Button>
      </Form>
<div class="reviews">
 {Reviews_.map(item => <div> {item}</div> )}
</>


    </div>
  );
}```

Then to get the stars rating value use props like... And make sure you call that property (function) inside your Starts component

const getRating =(value)=>{

setReviewsRating(value)
}

Here is the working version of your code. You should use key in your map and e.preventDefault() in your form submit function. As final touch you should set another state inside your form submit and show this value in a div or some html element. Also I see that you want to get child state into parent so you can call callback for this https://codesandbox.io/embed/brave-euler-ybp9cx?fontsize=14&hidenavigation=1&theme=dark

ReviewForm.js

export default function ReviewForm() {
  const [reviews, setReviews] = useState("");
  const [value, setValue] = useState("");
  const [star, setStar] = useState();
  const onChange = (e: any) => {
    setReviews(e.target.value);
  };

  const onSubmit = (e: any) => {
    e.preventDefault();
    setValue(reviews + " with " + star + " star ");
  };

  return (
    <div className="form-container">
      <Stars setStar={setStar} />
      <Form onSubmit={onSubmit}>
        <Input
          className="form-control"
          type="text"
          placeholder="Enter you review"
          value={reviews}
          onChange={onChange}
        />
        <br></br>
        <Button type="submit" className="btn btn-primary">
          Submit
        </Button>
        <div>{value}</div>
      </Form>
    </div>
  );
}

Stars.js

const Stars = ({ setStar }) => {
  const [rating, setRating] = useState(0);
  const [hover, setHover] = useState(null);

  const handleClick = (ratingValue) => {
    setRating(ratingValue);
    setStar(ratingValue);
  };

  return (
    <div>
      {[...Array(5)].map((star, i) => {
        const ratingValue = i + 1;
        return (
          <label key={i}>
            <input
              type="radio"
              name="rating"
              value={ratingValue}
              onClick={() => handleClick(ratingValue)}
            />
            <FaStar
              className="star"
              color={ratingValue <= (hover || rating) ? "gold" : "lightgray"}
              size={20}
              onMouseEnter={() => setHover(ratingValue)}
              onMouseLeave={() => setHover(null)}
            />
          </label>
        );
      })}
      <p>I rate this movie {rating + " stars"}</p>
    </div>
  );
};

export default Stars;
Related