1

I am exporting a const from one file and importing it into another like so:

constants.js

export const radio = {
  id: 0,
  name: 'station name',
  encodedName: 'stationName',
  url: 'http://www.some-station.io/',
  src: 'http://127.0.0.1:80/autodj',
};

App.js

import React, { Component } from 'react';
import RadioService from './services/radio';
import { radio } from './constants';

class App extends Component {
  constructor() {
    super();
    this.state = {
      stream: {
        np: undefined,
        src: undefined,
        playing: false
      }
    };
  }

  componentWillMount() {
    this.startStream();
  }

  startStream = () => this.setState({ stream: { np: radio.name, src: radio.src } });

  render() {
    return (
      <div>
        <h4>Hello World...</h4>
      </div>
    );
  }
}

export default App;

I'm expecting my initial state to be as set in the constructor, then on componentWillMount I'd like to set the state with the values from the constant file, before adding further logic around the component and stream.

I'm finding however, my state is not being updated, if I console log after called setState, the state is still undefined and if I introduce a method that required that value from state, later in the execution stack, it is not set.

example:

  startStream = () => {
    this.setState({ stream: { np: radio.name, src: radio.src } });
    this.exampleMethod();
  };

  exampleMethod = () => console.log(this.state);

This returns:

{stream: {…}}stream: {np: undefined, src: undefined, playing: false}

I can however set some values in the constructor, however trying to set further state is not applied

example 2:

class App extends Component {
  constructor() {
    super();
    this.state = {
      stream: {
        np: radio.name,
        src: radio.src,
        playing: false
      }
    };
  }

  componentWillMount() {
    this.startStream();
  }

  startStream = () => {
    this.setState({ ...this.state, stream: { playing: true } });
    this.exampleMethod();
  };
Harry Blue
  • 4,202
  • 10
  • 39
  • 78
  • I believe `setState` function is async. So you cannot get new state immediately after calling that function. Try to move the console log to render method. – Viki Theolorado Oct 27 '17 at 06:29
  • 1
    try to add `this.startStream = this.startStream.bind(this);` in the constructor – Nikita U. Oct 27 '17 at 06:31
  • 1
    Does this really not throw you an error? Because it should: "this" is not in the context of the function startStream. You need to bind it in the constructor using this.startStream = this.startStream.bind(this); Another thing: You should take the props in the constructor and pass it to the super class, so change it to constructor(props) { super(props); ... }. This will solve further issues with props not being updated. – Larce Oct 27 '17 at 06:34

2 Answers2

2

The setState is an asynchronous function. You cannot expect state to be update immediately after the setState statement.

However, you can inspect state by either:

  1. Putting a console.log(this.state) in your render() method.

  2. Or using a callback after setState

    this.setState({ ...this.state, stream: { playing: true } }, () => { console.log(this.state); // should show updated state });

Sarun UK
  • 6,210
  • 7
  • 23
  • 48
Naisheel Verdhan
  • 4,905
  • 22
  • 34
1

setState is asynchronous, so you will not get the new state if you console.log immediately after.

setState in reactjs is Async or Sync

anand
  • 565
  • 2
  • 9