Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React - TypeError: Cannot read property 'includes' of undefined

Tags:

reactjs

I'm new to React, sorry if this is too basic.

I have an input form and I'm trying to handle submits and changes to it, like so:

import { editMenuFormRules } from './forms/form-rules.js';

class Seeds extends Component{
  constructor (props) {
    super(props);
    this.state = { 
        formData: {
          coffee:''
        },
        menu:[],
        editMenuFormRules:editMenuFormRules,

    };
    this.handleSubmitCoffees = this.handleSubmitCoffees.bind(this);
    this.handleBeanFormChange = this.handleBeanFormChange.bind(this);
  };

componentDidMount() {
    if (this.props.isAuthenticated) {
      this.getSeeds();
    }
  };

getSeeds(event) {
    const {userId} = this.props
    const options = {
      url: `${process.env.REACT_APP_WEB_SERVICE_URL}/seeds/${userId}`,
      method: 'get',
      headers: {
        'Content-Type': 'application/json',
         Authorization: `Bearer ${window.localStorage.authToken}`
      }
    };
    return axios(options)
    .then((res) => {
      console.log(res.data.data)
      this.setState({
        menu: res.data.data[0].menu
      })
    })    
    .catch((error) => { console.log(error); });
  };

for handling submit and form change, I have:

handleSubmitCoffees(event) {
    event.preventDefault();
    const formType = this.props.formType
    const {userId} = this.props
    var headers = {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${window.localStorage.authToken}`
        }
    const data = {
      coffee: this.state.formData.coffee
    };
    if (formType === 'EditMenu' && this.state.menu.includes(this.state.formData.coffee)) {
      alert('This coffee already exists. Please add a new one.');
      return (<Redirect to='/seeds' />);
    };
    const url = `${process.env.REACT_APP_WEB_SERVICE_URL}/edit_menu/${userId}`;
    axios.post(url, data, headers)
      .then((res) => {
        this.clearForm()
        console.log(data);
      })
      .catch((err) => {
      if (formType === 'EditCoffee') {
        this.props.createMessage('Coffee edit failed.', 'Please review your entry');
      };
    });
  };

and:

handleBeanFormChange(event) {
    console.log(event)
    const obj = this.state.formData;
    obj[event.target.name] = event.target.value;
    this.setState(obj);
    this.validateForm();; 
  };

finally, my form:

<form onSubmit={ (event) => this.handleSubmitCoffees(event) }>
  <div className="field">
    <input
      name="coffee"
      className="input is-large"
      type="text"
      placeholder="Enter Coffee Name"
      value={this.state.formData.coffee}
      onChange={this.handleBeanFormChange}
     />
  </div>
</form>

when I input my first item at form, however, I'm getting the following error:

TypeError: Cannot read property 'includes' of undefined

which points to this line:

> 150 | if (formType === 'EditMenu' && this.state.menu.includes(this.state.formData.coffee)) {

am I not defining this.state.formData.coffee when I press enter at form?

What am I missing?

like image 330
8-Bit Borges Avatar asked Oct 11 '19 20:10

8-Bit Borges


2 Answers

const obj = this.state.formData;
obj[event.target.name] = event.target.value;
this.setState(obj); // <-- this is setting 'target.name: value'

This is effectively overwriting formData. I think what you are meaning to do is:

const obj = Object.assign({}, this.state.formData);
obj[event.target.name] = event.target.value;
this.setState({ formData: obj });

Do note that it's important to clone the formData object, as what you are doing is mutating the state, which is not desired.

like image 97
Yuan-Hao Chiang Avatar answered Nov 03 '22 09:11

Yuan-Hao Chiang


The problem is here, where there is a GET request for 'menu' value:

componentDidMount() {
    if (this.props.isAuthenticated) {
      this.getSeeds(); ///// <------------
    }
  };

There was a malformed json response object at backend:

response_object = {
              'status': 'success',
              'message': 'User does not have a menu yet',
              'data': [{"id": user.id,
                        "seeds": user.seeds,
                        "content": template}]
            }

                        //"menu": [] //----> key, value was missing

Therefore, there was no 'menu' value being fetched, and that's what 'undefined' refers to:

//GET request at `getSeeds()`
this.setState({
        menu: res.data.data[0].menu // <----- undefined
      })

no this.state.menu could be set at getSeeds(), at all.

Adding "menu": [] to response_object fixed it.

like image 37
8-Bit Borges Avatar answered Nov 03 '22 07:11

8-Bit Borges