NiceToMytyuk
NiceToMytyuk

Reputation: 4307

How to load dynamic data to react-native-chart-kit?

Actually i'm would load data dynamically to react-native-chart-kit but i can't find any documentation on how could i do it.

I have an API that give the data for each month where there was some income and the response look's like the following

[{"IMPORTO":722.51},{"IMPORTO":911},{"IMPORTO":1188.53},{"IMPORTO":12},{"IMPORTO":390.65},{"IMPORTO":54.98}]

I have yet a method where i fetch that data but i can't get how can i use it as dataset of the chart.

Here is the code of my Home.JS where i build the chart and GetData is the fetch function for API DATA:

  import React from 'react';
import {Text,View,Dimensions} from 'react-native';
import {LineChart} from "react-native-chart-kit";

const data = {
  labels: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"],
  datasets: [
    {
      data: []
    }
  ]
}
const chartConfig = {
  backgroundColor: "#e26a00",
  backgroundGradientFrom: "#fb8c00",
  backgroundGradientTo: "#ffa726",
  decimalPlaces: 2, // optional, defaults to 2dp
  color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
  labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
  style: {
    borderRadius: 16
  },
  propsForDots: {
    r: "6",
    strokeWidth: "2",
    stroke: "#ffa726"
  }
}

export default class Home extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      isLoading: true,
      dataSource: []
    };

  }

  componentDidMount() {
  this.GetData();
  }

  GetData = () => {
    return fetch('http://192.168.100.158:3000/data')
    .then((response) => response.json())
    .then((responseJson) => {
      this.setState({
        isLoading: false,
        dataSource: responseJson
      });
    })
    .catch((error) =>{
      console.error(error);
    });
  }

  render() {
    data.datasets[0].data = this.state.dataSource.map(value => value. IMPORTO);

    return (
      <View>
      <LineChart
      data={data}
      width={Dimensions.get("window").width} // from react-native
      height={220}
      yAxisLabel={"$"}
      chartConfig={chartConfig}
      bezier
      style={{
        marginVertical: 8,
        borderRadius: 16
      }}
      />
      </View>
    );
  }
}

I've tryed to set data = { this.state.dataSource.IMPORTO } but it doesn't work.

Upvotes: 3

Views: 9976

Answers (2)

Sabaoon Bedar
Sabaoon Bedar

Reputation: 3689

This would definitely work for creating dynamic chart using react-native-chart-kit:

import React, { Component } from "react";
import {
  Alert,
  StyleSheet,
  Text,
  View,
  ActivityIndicator,
  Dimensions,
  
} from "react-native";


import {
 LineChart,
  BarChart,
  PieChart,
  ProgressChart,
  ContributionGraph,
  StackedBarChart
} from "react-native-chart-kit";


class Linedchart extends Component {
  state = {
datasource:[]
  };


 
LineChart_Dynamic=()=>{


if (this.state.datasource){
if(this.state.datasource.length){

return(
<View>
  <Text>Bezier Line Chart</Text>
  <LineChart
    data={{
      labels: ["January", "February", "March", "April", "May", "June"],
      datasets: [
        {
          data:  this.state.datasource.map(item=>{
            return(
              item.students 
//you need to add your data here from JSON, and remember the data you are requesting should be integer.
            )
          })
          
        }
      ]
    }}
    width={Dimensions.get("window").width} // from react-native
    height={220}
    yAxisLabel="students"
    yAxisSuffix="k"
    yAxisInterval={1} // optional, defaults to 1
    chartConfig={{
      backgroundColor: "#e26a00",
      backgroundGradientFrom: "#fb8c00",
      backgroundGradientTo: "#ffa726",
      decimalPlaces: 2, // optional, defaults to 2dp
      color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
      labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
      style: {
        borderRadius: 16
      },
      propsForDots: {
        r: "6",
        strokeWidth: "2",
        stroke: "#ffa726"
      }
    }}
    bezier
    style={{
      marginVertical: 8,
      borderRadius: 16
    }}
  />
</View>
)

} else {


return(


<View style={{justifyContent:"center",alignItems:'center',flex:1}}>


<ActivityIndicator size="large"/>

</View>

)
  }



}else {


  return(
  
  
  <View style={{justifyContent:"center",alignItems:'center',flex:1}}>
  
  
 <Text>no data found</Text>
  
  
  </View>
  
  
  
  )}

  }



//fetch your own data from here:



 get_chart=()=>{

  
        
              fetch('http://192.168.18.7:8000/api/linechart', {
                method: 'GET',
                headers: {
                  Accept: 'application/json',
                  'Content-Type': 'application/json',
                },
                
              })
                .then(response => response.json())
          
                .then(response => {
                 this.setState({datasource:response})
             
                })
                .catch(error => {
                
                });
            




}










  componentDidMount=()=>{
   
    this.get_chart()
    
  }


  render() {


return(
<View>

{this.LineChart_Dynamic()}

</View>

)


}

}



export default Linedchart;

if you are interested in explanation see this article:https://baidar-sabaoon.medium.com/how-to-make-dynamic-charts-in-react-native-using-react-native-chart-kit-48e9e5f41485

Upvotes: 1

M Polak
M Polak

Reputation: 877

In your render method, change the data to come from the state.

render() {

    data.datasets[0].data = this.state.dataSource.map(value => value.IMPORTO);

    return (
      <View>
          <LineChart
              data={data}
              width={Dimensions.get("window").width} // from react-native
              height={220}
              yAxisLabel={"$"}
              chartConfig={chartConfig}
              bezier
              style={{
                    marginVertical: 8,
                    borderRadius: 16
              }}
          />
      </View>
    );
}

Now, when the asynchronous call "GetData()" finishes, it will update the state, and the component will re-render with the new data.

You could also set the initial values in the state itself:

constructor(props) {
    super(props);
    this.state = {
       isLoading: true,
       data: {
           labels: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"],
           datasets: [
               {
                   data: []
               }
           ]
       }
    }
}

GetData = () => {
    const self = this;

    return fetch('http://192.168.100.158:3000/data')
        .then((response) => response.json())
        .then((responseJson) => {

            // clone the data from the state
            const dataClone = {...self.state.data}

            const values = responseJson.map(value => value.IMPORTO);

            dataClone.datasets[0].data = values;
    
            self.setState({
                isLoading: false,
                data: dataClone,
            });
    })
    .catch((error) =>{
      console.error(error);
    });
}

render() {

    // since we're now referencing this.state.data, its value 
    // will be updated directly when we update the state
    
    return (
      <View>
          <LineChart
              data={this.state.data}
              width={Dimensions.get("window").width} // from react-native
              height={220}
              yAxisLabel={"$"}
              chartConfig={chartConfig}
              bezier
              style={{
                  marginVertical: 8,
                  borderRadius: 16
              }}
          />
      </View>
    );
}

Upvotes: 4

Related Questions