Kathy
Kathy

Reputation: 107

How to set state of the value when using react-rating component in my form?

I'm using React Rating (https://github.com/dreyescat/react-rating) and I'm not sure how to set state for the values for my 2 ratings. The other fields are fine.

I'm able to get the values to show in console. I don't know how to set state in handleRatingChange().

Also, when I fill out the other fields after I have done the ratings, the ratings resets.

Here is my code:

var Rating = require('react-rating')

class Assignment extends Component {

  constructor(props) {
    super(props)
    this.state = {
      form: {
        site: '',
        facilityRate: '',
        staffRate: '',
        theList: 'off'
      }
    }
  }

  handleChange(event) {
    const formState = Object.assign({}, this.state.form);
    formState[event.target.name] = event.target.value;
    this.setState({ form: formState });
    console.log(formState);
  }

  handleRatingChange(rating) {
    console.log('rating', rating);
  }

  render() {
    return (

      <Grid>
        <PageHeader id='header'>
          Track your assignment <small className='subtitle'>Let us make a record of your assignment.</small>
        </PageHeader>

        <form id='assignment-form'>

          <h3>Record your assignment</h3>

          <Row>
            <Col xs={5} md={5}>
              <FormGroup>
                <ControlLabel id='site'>Site Name</ControlLabel>
                <FormControl type='text' name='site'
                  onChange={this.handleChange.bind(this)}
                  value={this.state.form.site}
                />
              </FormGroup>

              <FormGroup>
                <ControlLabel id='facilityRate'>Rate the Facility</ControlLabel><br />
                <Rating
                  name='facilityRate'
                  emptySymbol={<img src='../star-empty.png' className='icon' alt='empty star' />}
                  fullSymbol={<img src='../star-full.png' className='icon' alt='filled star' />}
                  onChange={this.handleRatingChange} />
              </FormGroup>

              <FormGroup>
                <ControlLabel id='staffRate'>Rate the Staff</ControlLabel><br />
                <Rating
                  name='staffRate'
                  emptySymbol={<img src='../star-empty.png' className='icon' alt='empty star' />}
                  fullSymbol={<img src='../star-full.png' className='icon' alt='filled star' />}
                  onChange={this.handleRatingChange} />
              </FormGroup>

              <FormGroup>
                <ControlLabel id='theList'>The List
                          <br /><i>Add it to my favorites.</i>
                </ControlLabel><br />
                <Checkbox
                  name='theList'
                  checked={this.state.theList}
                  onChange={this.handleChange.bind(this)}>Add to The List
                            </Checkbox>
              </FormGroup>
            </Col>
          </Row>

          <Row>
            <Col xs={5} md={5}>
              <Button type='submit' className='btn btn-secondary' id='submit'>Submit Assignment</Button>
            </Col>
          </Row>


        </form>
      </Grid>
    );
  }
}

Upvotes: 3

Views: 3914

Answers (1)

John
John

Reputation: 116

Add an initial rating property, for example initialRating={this.state.facilityRating} for the facilityRate Rating and then initialRating={this.state.staffRating} for the staffRate Rating.

<Rating name='facilityRate' 
    emptySymbol={<img src='../star-empty.png' 
    className='icon' alt='empty star' />}
    initialRating={this.state.form.facilityRate}
    fullSymbol={<img src='../star-full.png' className='icon' 
    alt='filled star' />}
    onChange={this.handleStaffRatingChange} />

<Rating name='staffRate' 
        emptySymbol={<img src='../star-empty.png' 
        className='icon' alt='empty star' />}
        initialRating={this.state.form.staffRate}
        fullSymbol={<img src='../star-full.png' className='icon' 
        alt='filled star' />}
        onChange={this.handleStaffRatingChange} />

It's also important to have a default value in your state, since at the beginning, it's going to be undefined.

constructor(props) {
    super(props)
    this.state = {
      form: {
        site: '',
        facilityRate: '', <-- Sets the initial value for facility
        staffRate: '', <-- Sets the initial value for staff
        theList: 'off'
      },
    }
  }

Then split your rating function into two functions.

handleStaffRatingChange = (rating) => {
    this.setState({...this.state, form: {...this.state.form, staffRate: rating}});
}

handleFacilityRatingChange = (rating) => {
    this.setState({...this.state, form: {...this.state.form, facilityRate: rating}});
}

The reason we did this is so that each function will alter a specific area in the state. Each rating has to look at the state to determine what it's value is, therefore they cannot be the same value in the state. The handleStaffRatingChange targets this.state.form.staffRate and handleFacilityRatingChange targets this.state.form.facilityRate.

It is possible to design a single function to handle both, but since you're fairly new to react, I'm don't want to throw too much at you at once.

These functions are adding a spread operator to copy the state and then update the key 'facilityRating' or 'staffRating' with the new value of 'rating'. I'm also doing a lambda here to take care of binding.

It also looks like your form is reseting because you're replacing the state instead of adding to it. Use the spread operator again.

handleChange(event) {
        const formState = Object.assign({}, this.state.form);
        formState[event.target.name] = event.target.value;
        this.setState({ ...this.state, form: formState });
        console.log(formState);
    }

Upvotes: 2

Related Questions