socialb
socialb

Reputation: 135

ReactJS Fetch Type error in render when storing an object in state

I'm quite new to react and i'm trying to get an object (session) from a server and edit it using a form and after changes being made, store it using a post to the server.

I've made a component that fetches data from the server and stores it into the state.

The problem is that the render section gives an error because it probably doesn't know the subfields of the state object yet. I'm referring to 'session.name' and a couple of other fields but that gives an error. (TypeError: this.state.session is null[Meer info])

class SessionFirstTab extends React.Component {
    constructor() {
        super();
        this.state = { 
            session: null,
            statechanged: false
        };  
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.getSessionData = this.getSessionData.bind(this)

    }

    componentDidMount() {
        this.getSessionData()
    }

    getSessionData() {
        var myHeaders = new Headers();
        myHeaders.append("Content-Type", 'application/x-www-form-urlencoded');
        myHeaders.append("x-access-token", 'eyJhbGciOiJIUzI1....');
        myHeaders.append("userid", "5904ab94835a710868d19fa2");
        myHeaders.append("id", this.props.sessionid);

        var myInit = { method: 'GET',
               headers: myHeaders,
               mode: 'cors',
               cache: 'default' };


       fetch('http://localhost:3000/api/session',myInit) 
      .then(function(response) {  
          if (response.status !== 200) {  
            console.log('Looks like there was a problem. Status Code: ' +  
              response.status); 
            return;  
          }
        //   Examine the text in the response  
         response.json().then(function(data) {  
         data => this.setState({session: data});

          });  
        }  
      )  
      .catch(function(err) {    
        console.log('Fetch Error', err);  
      });



    } //////////////END getSessionInfo


    handleChange(event) {
        const target = event.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;

        this.setState({ statechanged: true});
        this.setState({session: {[name]: value}});
    }


    handleSubmit(event) {
    // console.log(this.state.session.name);
        event.preventDefault();
    }



    render() {
        return (

     <article className="article">
    <h2 className="article-title">Edit Session </h2>

    <section className="box box-default">
      <div className="box-body padding-xl">

        <section className="box box-default">
          <div className="box-body no-padding">
           <Tabs>
    <Tab label="Properties" >
      <div style={styles}>

       <form role="form" onSubmit={this.handleSubmit}>





          <div className="divider divider-lg" />
    <div className="row">

      <div className="col-xl-6">
        <div className="box box-default">
          <div className="box-body">
            <div className="icon-box ibox-center">
              <div className="ibox-icon">
                <a href="javascript:;"><i className="material-icons">settings</i></a>
              </div>
              <h3>General</h3>
               <div className="form-group">
             <TextField name="name" id="name" hintText="Give this session a description" floatingLabelText="Name"  floatingLabelFixed defaultValue={this.state.session.name} onChange={this.handleChange}/><br />
          </div>

Upvotes: 1

Views: 382

Answers (2)

Chase DeAnda
Chase DeAnda

Reputation: 16441

You just need to handle when session is null. An easy solution would be:

render() {
    const session_name = this.state.session.name || '';
        return (

     <article className="article">
    <h2 className="article-title">Edit Session </h2>

    <section className="box box-default">
      <div className="box-body padding-xl">

        <section className="box box-default">
          <div className="box-body no-padding">
           <Tabs>
    <Tab label="Properties" >
      <div style={styles}>

       <form role="form" onSubmit={this.handleSubmit}>





          <div className="divider divider-lg" />
    <div className="row">

      <div className="col-xl-6">
        <div className="box box-default">
          <div className="box-body">
            <div className="icon-box ibox-center">
              <div className="ibox-icon">
                <a href="javascript:;"><i className="material-icons">settings</i></a>
              </div>
              <h3>General</h3>
               <div className="form-group">
             <TextField name="name" id="name" hintText="Give this session a description" floatingLabelText="Name"  floatingLabelFixed defaultValue={session_name} onChange={this.handleChange}/><br />
          </div>

Upvotes: 0

Facundo La Rocca
Facundo La Rocca

Reputation: 3866

I think the only thing you need to do is just to check whether session is null or not. I usually use two approaches, always depending on what I need.

Approach 1:

if there is session, render session.name, else render a empty string.

<TextField name="name" id="name" hintText="Give this session a description" floatingLabelText="Name"  floatingLabelFixed defaultValue={this.state.session !== null ? this.state.session.name : ''} onChange={this.handleChange}/>

This way forces you to check also inside your handlers. In your case you will have to check inside handleChange and also in handleSummit. So in my opinion, you should try with the second approach.

Approach 2:

If you have session, render the form, else render some loading graph

if(this.state.session){
  return (
    <form role="form" onSubmit={this.handleSubmit}>
      ... your staff here   
    </form>
  );
} else {
  return (
    <div>
      We are waiting for the session
    </div>
  );
}

Particularly, I would not store the whole session in the state, but I would store just the properties I needed. I mean, I would store this.state.name. Just for semantic and responsabilities concerns. Why? I'm supposing that your session has many things that the component does not need to know, so then it should not be there. But we could have a good discussion about that.

Hope It helps, If you feel like you need to clarify let me know, I will help.

Upvotes: 1

Related Questions