Pia
Pia

Reputation: 3

How to update the value in render() in React?

I want to display the data I get from the websocket. The render funtion gets called when the isn't already there. I tried to update it with this.state when the websocket has sent the data but it is not working. I'm using recharts to display the BarChart and in data I need the value from the WebSocket.

index.js

import _ from 'lodash';
import style from './style.css';
import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom';
import {
  BarChart, Bar, Cell, XAxis, YAxis, CartesianGrid, Tooltip, Legend, LabelList, Label
} from 'recharts';

var data;

class Example extends React.Component {

    constructor(props) {
  super(props);
  //setting a default value
  this.state = { data: [{time:23.30,value:288.65},{Energy:0,value:0.0}] };
}

//componentDidMount() {
    //this.state = { data: data };
    //console.log("compMount");
//}

  render() {
      //verbinde();
      var connection = new WebSocket('ws://next-gen-rz.hs-harz.de:8080/fhem_prototyp2/Test');
        connection.onopen = function () {
            connection.send('day');
            console.log("gesendet: day");
        };
            // Log errors
        connection.onerror = function (error) {
            console.log('WebSocket Error ' + error);
        };

        // Log messages from the server
        connection.onmessage = function (e) {
            console.log('Server: ' + e.data);
            this.setState = {data: e.data };
        };


    return (

      <BarChart
        width={800}
        height={500}
        data={this.state.data}
        margin={{
          top: 5, right: 30, left: 20, bottom: 5,
        }}
      >
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="time" tick={{ fill: 'white'}}/>
        <YAxis tick={{ fill: 'white' }} label={{ value: 'kWh', angle: -90, position: 'insideLeft' }}>
        </YAxis>
        <Bar name="Wochenverbrauch" dataKey="value" fill="#f59f4a" >
        <LabelList dataKey="value" position="top" fill='white'/>
        </Bar>
      </BarChart>
    );
  }

}
ReactDOM.render(<Example />, document.getElementById("left"));

Upvotes: 0

Views: 3504

Answers (2)

Olivier Boiss&#233;
Olivier Boiss&#233;

Reputation: 18083

You should open the websocket connection only once in the componentDidMount method lifecycle.

To update the state, you should call the setState function

You also need to close the websocket connection in the componentWillUnmount method to avoid memory leaks

class Example extends React.Component {

 constructor(props) {
   super(props);
   //setting a default value
   this.state = { data: [{time:23.30,value:288.65},{Energy:0,value:0.0}] };
 }

 componentDidMount() {
    const that = this;

    that.connection = new WebSocket(
      'ws://next-gen-rz.hs-harz.de:8080/fhem_prototyp2/Test'
    );

    that.connection.onopen = function () {
        that.connection.send('day');
    };
        // Log errors
    that.connection.onerror = function (error) {
        console.log('WebSocket Error ' + error);
    };

    // Log messages from the server
    that.connection.onmessage = function(e) {
        console.log('Server: ' + e.data);
        that.setState({data: e.data });
    };
 }

 componentWillUnmount() {
    this.connection && this.connection.close();
 }

 render() {
   return (
     <BarChart
       width={800}
       height={500}
       data={this.state.data}
       margin={{top: 5, right: 30, left: 20, bottom: 5}}
     >
      <CartesianGrid strokeDasharray="3 3" />
      <XAxis dataKey="time" tick={{ fill: 'white'}}/>
      <YAxis 
          tick={{ fill: 'white' }} 
          label={{ value: 'kWh', angle: -90, position: 'insideLeft' }}
      />
      <Bar name="Wochenverbrauch" dataKey="value" fill="#f59f4a" >
        <LabelList dataKey="value" position="top" fill='white'/>
      </Bar>
    </BarChart>
  );
 }
}

Upvotes: 2

JBaczuk
JBaczuk

Reputation: 14589

You can't update by mutating the state, you need to call the function:

this.setState(newState)

and provide the newState object. See https://reactjs.org/docs/react-component.html#setstate

Also, you can't set the state in the render function, you need to get the data in componentDidMount, for example, and then set the state there.

Upvotes: 1

Related Questions