dooglex
dooglex

Reputation: 65

React component not getting default state

Trying to learn React/RoR and in this simple test app I have a 'searchapp' react app. That sets a default for the language radioboxes.

import React from 'react'
import ReactDOM from 'react-dom'

import axios from "axios";

import SearchForm from "./searchForm";

class SearchApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      searchStrings: [],
      subjectName: "",
      language: 'English',
      region: ""
    };
    this.getSearchStrings = this.getSearchStrings.bind(this);
  }
  componentDidMount() {
    this.getSearchStrings();
  }
  handleClickLang  = changeEvent => {
  this.setState({
    language: changeEvent.target.value
  });
};

  getSearchStrings() {
    axios
      .get("/api/v1/search_strings")
      .then(response => {
        const searchStrings = response.data;
        this.setState({searchStrings});
      })
      .catch(error => {
        console.log(error);
      });
  }
  render() {
    return (
    <>
    <SearchForm />
    </>
  );
  }
}

and then in the searchForm component I use that state to set and switch between two radio buttons.

class SearchForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.subjRef = React.createRef();
    //this.handleClickLang = this.handleClickLang.bind(this);
  }
  componentDidMount() {
    this.setState({
      language: 'English'
    });
  }
  handleSubmit(e) {
    e.preventDefault();
    window.alert("sometext");
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit} className="my-3">
       <div className="form-row">
       <div className="form-group col-md-8">
       <p>Choose language</p>
       </div>
       <div className="form-row">
       <div className="form-check">
         <label>
           <input
             type="radio"
             name="react-tips"
             value="English"
             checked={this.state.language === 'English'}
             onChange={this.handleClickLang}
             className="form-check-input"
           />
           English
         </label>
       </div>
       <div className="form-check">
         <label>
           <input
             type="radio"
             name="react-tips"
             value="Russian"
             checked={this.state.language === 'Russian'}
             onChange={this.handleClickLang}
             className="form-check-input"
           />
           Russian
         </label>
       </div>

However when I run this I get the following error: Uncaught TypeError: Cannot read properties of null (reading 'language')

I thought this was erroring because it cannot find a default language, however I initialised language to 'English' in the constructor for the SearchApp.

Is this me not understanding React state enough? Any help much appreciated.

Upvotes: 1

Views: 424

Answers (2)

dooglex
dooglex

Reputation: 65

Adding a followup here for future reference.

As suggested by @Thor84no the problem was not adding state = {} to intialise state in the sub component.

Upvotes: 0

Nacho
Nacho

Reputation: 974

In the componentDidMount i feel the language is getting to null, you can try the following:

Trying to learn React/RoR and in this simple test app I have a 'searchapp' react app. That sets a default for the language radioboxes.

import React from 'react'
import ReactDOM from 'react-dom'

import axios from "axios";

import SearchForm from "./searchForm";

class SearchApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      searchStrings: [],
      subjectName: "",
      language: 'English',
      region: ""
    };
    this.getSearchStrings = this.getSearchStrings.bind(this);
  }
  componentDidMount() {
    this.getSearchStrings();
  }
  handleClickLang  = changeEvent => {
  this.setState({
    language: changeEvent.target.value
  });
};

  getSearchStrings() {
    axios
      .get("/api/v1/search_strings")
      .then(response => {
        const searchStrings = response.data;
        this.setState({searchStrings,language: 'English'});
      })
      .catch(error => {
        console.log(error);
      });
  }
  render() {
    return (
    <>
    <SearchForm language={this.state.language}/>
    </>
  );
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

And in the SearchForm component pass the language via props

class SearchForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.subjRef = React.createRef();
    //this.handleClickLang = this.handleClickLang.bind(this);
  }
 
  handleSubmit(e) {
    e.preventDefault();
    window.alert("sometext");
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit} className="my-3">
       <div className="form-row">
       <div className="form-group col-md-8">
       <p>Choose language</p>
       </div>
       <div className="form-row">
       <div className="form-check">
         <label>
           <input
             type="radio"
             name="react-tips"
             value="English"
             checked={this.props.language === 'English'}
             onChange={this.handleClickLang}
             className="form-check-input"
           />
           English
         </label>
       </div>
       <div className="form-check">
         <label>
           <input
             type="radio"
             name="react-tips"
             value="Russian"
             checked={this.props.language === 'Russian'}
             onChange={this.handleClickLang}
             className="form-check-input"
           />
           Russian
         </label>
       </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

But there are several more things:

  • Why are you also having language state in searchForm, you can have it in Search component and pass it via props
  • Yo are not initializing any state in the constructor in your SearchForm component

Upvotes: 1

Related Questions