OunknownO
OunknownO

Reputation: 1196

Uncaught TypeError: Cannot read property 'nameOfCity' of null at App.render

When I compile my files and run in console log I get this error

enter code here
Uncaught TypeError: Cannot read property 'nameOfCity' of null     at App.render

They all "meet" at App component(I am using 'create-react-app' pack from facebook). I presume that it should load first Form Container and in it logic set initial state to empty and then Weather info data comes. Or am I wrong?

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import {FormContainer} from './containers/FormContainer';
import WeatherInfo from './components/WeatherInfo';

class App extends Component {

render() {
return (
  <div className="App">
    <div className="App-header">
      <img src={logo} className="App-logo" alt="logo" />
      <h2>Weather App</h2>
    </div>
    <p className="App-intro">
      To get started, edit <code>src/App.js</code> and save to reload.
    </p>
      <FormContainer label="Name of the city:"/>
      <WeatherInfo
          nameOfCity={this.state.nameOfCity}
          weatherDescription={this.state.weatherDescription}
          windSpeed={this.state.windSpeed}
          temperature={this.state.temperature}
          maxTemperature={this.state.maxTemperature}
          minTemperature={this.state.minTemperature}
      />
  </div>
);
}
}
export default App;

Form Container

import React, {Component} from 'react';
import SearchBar from '../components/SearchBar';

class FormContainer extends Component {

constructor(props) {
    super(props);
    this.state = {
        cityName: '',
        nameOfCity:'',
        weatherDescription:'',
        windSpeed:'',
        temperature:'',
        maxTemperature:'',
        minTemperature:''
    };
    this.handleFormSubmit = this.handleFormSubmit.bind(this);
    this.handleCityName = this.handleCityName.bind(this);
}

handleFormSubmit(e) {
    e.preventDefault();

    const SendForm = {
        cityName: this.state.cityName
    };
    console.log(SendForm);
    fetch(`http://api.openweathermap.org/data/2.5/forecast/weather?q=${SendForm.cityName}&units=metric&APPID=********`)
        .then(res => res.json())
        .then(results => {
            this.setState({
                nameOfCity: results.city.name,
                weatherDescription: results.list[0].weather[0].description,
                windSpeed: results.list[2].wind.speed,
                temperature: results.list[0].main.temp,
                maxTemperature: results.list[0].main.temp_max,
                minTemperature: results.list[0].main.temp_min
            });
        });
}

handleCityName(value) {
    this.setState({ cityName: value });
}

render() {
    return (
        <div>
        <form onSubmit={this.handleFormSubmit}>
            <label>{this.props.label}</label>
            <SearchBar
                name="CityName"
                type="text"
                value={this.state.cityName}
                placeholder="search"
                onChange={this.handleCityName}
            />
            <button type="submit"
                    className=""
                    value='Submit'
                    placeholder="Search" />
        </form>

        </div>
    );
}
}

export {FormContainer};

Search bar component

import React, {Component} from 'react';

const SearchBar = (props) => (
<div>
    <label>{props.label}</label>
    <input name={props.name} type={props.inputType} value={props.value} placeholder={props.placeholder} onChange={(e)=>props.onChange(e.target.value)}/>
</div>
);

export default SearchBar;

and Weather Info component

import React, {Component} from 'react';

const WeatherInfo = (props) => (
<div>
    <ul>
        <li>{props.nameOfCity}</li>
        <li>{props.weatherDescription}</li>
        <li>{props.windSpeed}</li>
        <li>{props.temperature}</li>
        <li>{props.maxTemperature}</li>
        <li>{props.minTemperature}</li>
    </ul>
</div>
);

export default WeatherInfo;

Upvotes: 0

Views: 692

Answers (4)

user3639680
user3639680

Reputation: 71

These type of error occurs when you try to use attributes of non existing data. In this case this.state don't have value i.e. its null. So make sure your this.state have desired value by some manipulation as per your functionality.

Upvotes: 0

Jack
Jack

Reputation: 26

You're trying to read nameOfCity from this.state in App, but your App component does not hold state.

You can have FormContainer use context and render WeatherInfo as a child:

class FormContainer extends Component {
  ...
  static childContextTypes = {
    nameOfCity: React.PropTypes.string
  }
  getChildContext() {
    return {
      nameOfCity: this.state.nameOfCity
    }
  }
 render: () {
   ...
   </form>
   {this.children}
 }

}

App.jsx:

<FormContainer label="Name of the City:">
  <WeatherInfo />
</FormContainer>

WeatherInfo.jsx:

class WeatherInfo extends React.Component {
  static contextTypes = {
    nameOfCity: React.PropTypes.string
  }
  render: () {
    <div>
      <ul>
        <li>{this.context.nameOfCity}</li>
        ...
  }
}

OR you can store state in App, and have FormContainer change App.state either by passing a prop, or by using context.

Upvotes: 1

Mayank Shukla
Mayank Shukla

Reputation: 104379

Issue is u r using this.state in App component, and in App component u didn't define any state, that's why it is throwing the error, can't read Cannot read property 'nameOfCity' of null, because state is null. U need to define state in App component and then pass this state values in props and use those values in other component.

Upvotes: 0

Diego Faria
Diego Faria

Reputation: 9185

The error is occurring at <WeatherInfo nameOfCity={this.state.nameOfCity} because at this point you don't have nameOfCity in the App component state.

In your code, the nameOfCity variable is inside FormContainer component state. If you want to use it across the components, you should have the state at the App component.

Upvotes: 1

Related Questions