Apex chart doesn't display immediately - reactjs

I have the following code for a apex chart to be displayed based on value
import React, { Component, Fragment,useState } from "react";
import RestAPI from "services/api";
import axios from "axios";
import Select from 'react-select';
import "d3-transition";
import "tippy.js/dist/tippy.css";
import "tippy.js/animations/scale.css";
/* Chart code */
// Themes begin
// Themes end
import {
Button,
Label,
FormGroup,
Form,
} from "reactstrap";
import ReactApexChart from "react-apexcharts";
import Loader from "react-loader-spinner";
class BarChart extends Component {
constructor(props){
super(props);
this.selectValue=this.selectValue.bind(this)
this.state = {
selectValue:"",
items:[],
weights:[],
isLoaded:true,
showViz:false,
series: [],
options: "",
};
}
selectValue (e) {
var selectValue=this.state.selectValue;
selectValue=e.value;
fetch("http://127.0.0.1:8000/api/values/"+selectValue)
.then(response => response.json())
.then(json => {
this.state.series=[]
var {items,weights}=this.state;
this.setState({
isLoaded:true,
items:json.keywords,
weights:json.weights,
series: [{ name: "Keywords", data: weights }],
options:{
chart: {
type: 'bar',
},
title:{
text:"Top 10 values"
},
plotOptions: {
bar: {
horizontal: true,
}
},
xaxis:{
categories: items
},
grid: {
xaxis: {
show:false,
lines: {
show: false
},
axisTicks:{
show:false,
offsetX: 0,
offsetY: 0
},
axisBorder:{
show:false
}
}
},
yaxis: {
reversed: false,
axisTicks: {
show: false
}
}
},
})
});
this.state.showViz=true;
}
render() {
var {selectValue,items,weights,isLoaded,options,series,showViz}=this.state;
const yeardata = [
{
value: "1",
label: "1"
},
{
value: "2",
label: "2"
},
{
value: "3",
label: "3"
},
{
value: "4",
label: "4"
},
{
value: "5",
label: "5"
},
{
value: "6",
label: "6"
},
{
value: "7",
label: "7"
},
{
value: "8",
label: "8"
},
{
value: "9",
label: "9"
},
{
value: "10",
label: "10"
}
];
//var{items,arr_keys,arr_vals}=this.state;
if(isLoaded){
return (
<>
{ console.log("the values are:",items)}
{ console.log("the values are:",weights)}
{ console.log("the values are:",options)}
{ console.log("the values are:",series)}
<Form role="form" >
<FormGroup>
<h2>Top 10 values</h2>
<Label>Select an Value</Label>
<Select placeholder="Select Option" options={yeardata} value={yeardata.find(obj => obj.value === selectValue)}
onChange={this.selectValue}
/>
<br></br>
{this.state.showViz?(
<ReactApexChart options={this.state.options} series={this.state.series} type="bar" height={250} />):
(<Loader type="Puff">
</Loader>)}
</FormGroup>
</Form>
</>
);
}
else{
return(
<>
</>
)
}
}
}
export default BarChart;
I want to display the chart when I select a value,but it is not displaying.Instead if I select another value,the previous value is displayed.Also,initially a blank plot is rendered which I don't want.Also,the loader is displayed as soon as the page is loaded which I want to avoid too.How could I resolve this?
Screenshot of rendered image:

You never set isLoaded false, so it's always true. You need to set isLoaded to false in constructor and after you receive response - true:
React state is async, you can't set a value just like this this.state.showViz=true; , you need to use this.setState each time you want to change your state and don't forget to put all other state data
this.setState({...this.state, showViz: true});
And as I've understood your logic correctly you need to put this code inside last .then:
this.setState({
isLoaded:true,
items:json.keywords,
weights:json.weights,
showViz: true,
...
You never set selectValue, so you don't need this code var selectValue=this.state.selectValue
Final code:
import React, { Component, Fragment, useState } from "react";
import RestAPI from "services/api";
import axios from "axios";
import Select from "react-select";
import "d3-transition";
import "tippy.js/dist/tippy.css";
import "tippy.js/animations/scale.css";
/* Chart code */
// Themes begin
// Themes end
import { Button, Label, FormGroup, Form } from "reactstrap";
import ReactApexChart from "react-apexcharts";
import Loader from "react-loader-spinner";
class BarChart extends Component {
constructor(props) {
super(props);
this.selectValue = this.selectValue.bind(this);
this.state = {
selectValue: "",
items: [],
weights: [],
isLoaded: true,
showViz: false,
series: [],
options: "",
};
}
selectValue(e) {
var selectValue = this.state.selectValue;
selectValue = e.value;
fetch("http://127.0.0.1:8000/api/values/" + selectValue)
.then((response) => response.json())
.then((json) => {
var { items, weights } = this.state;
this.setState({
isLoaded: true,
items: json.keywords,
weights: json.weights,
showViz: true,
series: [
{
name: "Keywords",
data: weights,
},
],
options: {
chart: {
type: "bar",
},
title: {
text: "Top 10 values",
},
plotOptions: {
bar: {
horizontal: true,
},
},
xaxis: {
categories: items,
},
grid: {
xaxis: {
show: false,
lines: {
show: false,
},
axisTicks: {
show: false,
offsetX: 0,
offsetY: 0,
},
axisBorder: {
show: false,
},
},
},
yaxis: {
reversed: false,
axisTicks: {
show: false,
},
},
},
});
});
}
render() {
var {
selectValue,
items,
weights,
isLoaded,
options,
series,
showViz,
} = this.state;
const yeardata = [
{
value: "1",
label: "1",
},
{
value: "2",
label: "2",
},
{
value: "3",
label: "3",
},
{
value: "4",
label: "4",
},
{
value: "5",
label: "5",
},
{
value: "6",
label: "6",
},
{
value: "7",
label: "7",
},
{
value: "8",
label: "8",
},
{
value: "9",
label: "9",
},
{
value: "10",
label: "10",
},
];
if (isLoaded) {
return (
<>
{console.log("the values are:", items)}
{console.log("the values are:", weights)}
{console.log("the values are:", options)}
{console.log("the values are:", series)}
<Form role="form">
<FormGroup>
<h2> Top 10 values </h2> <Label> Select an Value </Label>
<Select
placeholder="Select Option"
options={yeardata}
value={yeardata.find((obj) => obj.value === selectValue)}
onChange={this.selectValue}
/>
</br>
{this.state.showViz ? (
<ReactApexChart
options={this.state.options}
series={this.state.series}
type="bar"
height={250}
/>
) : (
<Loader type="Puff"></Loader>
)}
</FormGroup>
</Form>
</>
);
} else {
return <></>;
}
}
}

Related

Changing object in array using useState

I'd like to change each Data[0].datasets label using the array in Axisstate
I tried to put Axis's label to each Data label but i doesn't work, and it's not what i expected it would be.
both are changed to as same as the last one that i write.
and I'm trying to add more elements to datasets using the AxisHandler function to use push.
and It's doesn't change as soon as i click AxisUpdatefunction.
I'd like to know why it happens and what i should do .
Thank you in advance.
my code is like this:
import React, { useState } from "react";
import { Data, AppendData } from "./Data";
const Changeable = () => {
const [Axis, setAxis] = useState([]);
const changeHandler = index => e => {
setAxis(Axis =>
Axis.map((el, i) => (i === index ? { ...el, label: e.target.value } : el))
);
};
const AxisHandler = e => {
setAxis([
...Axis,
{
label: "",
data: "",
backgroundColor: "",
},
]);
Data[0].datasets.push(AppendData);
};
const AxisUpdate = () => {
if (Data[0].datasets[1].label) {
Data[0].datasets[1].label = Axis[0].label;
}
if (Data[0].datasets[2].label) {
Data[0].datasets[2].label = Axis[1].label;
}
};
return (
<div>
<button onClick={AxisHandler}>addAxis</button>
<>
{Axis.map((data, index) => (
<>
<input
placeholder={index + 1}
type="text"
onChange={changeHandler(index)}
/>
</>
))}
</>
<button onClick={AxisUpdate}>changeLabel</button>
<br />
<h1>{Data[0].datasets[0].label}</h1>
<br />
<h1>{Data[0].datasets[1] && Data[0].datasets[1].label}</h1>
<br />
<h1>{Data[0].datasets[2] && Data[0].datasets[2].label}</h1>
</div>
);
};
export default Changeable;
Data and AppendData
export const defaultLabels = [
"0",
"0",
"0",
"0",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
];
export const defaultDatas = [
13000, 11000, 9000, 4000, 14000, 16000, 20000, 11000, 14000, 11200, 12000,
12000,
];
export const defaultBackgroundColor = [
"#ff6385e1",
"#36a3ebf0",
"#ffcf56c8",
"#4bc0c0be",
"#9966ffa2",
"#ffa040b2",
];
export let AppendData = {
label: "dataSetting",
data: defaultDatas,
backgroundColor: defaultBackgroundColor,
};
export let Data = [
{
labels: defaultLabels,
datasets: [
{
label: "First",
data: defaultDatas,
backgroundColor: defaultBackgroundColor,
},
],
}, ///1번
{
labels: defaultLabels,
datasets: [
{
label: "Second",
data: defaultDatas,
backgroundColor: defaultBackgroundColor,
},
],
},
{
labels: defaultLabels,
datasets: [
{
label: "Third",
data: defaultDatas,
backgroundColor: defaultBackgroundColor,
},
],
},
]; ///2번

React Data Grid: Custom DropDown Editor: value is not getting updated. Grid is not getting enabled for editing

on react-data-grid 7.0.0-beta
I read through the most recent demos provided in git repo for react-data-grid and implemented a custom dropdown for my use case.
Dropdown seems to be working but it is not updating the grid data upon selection. The editable property doesn't seem to be working either.
test code is implemented here:
Sandbox: https://codesandbox.io/s/react-data-grid-custom-dropdown-editor-kcy5n
export const EntryCriteriaGrid = () => {
const columns = [
{
key: "r1",
name: "Criteria",
width: "50%",
resizable: true,
editable: true
},
{
key: "status",
name: "Status",
editor: DropdownCustomEditor,
editorOptions: {
editOnClick: true
},
editable: true
},
{ key: "tracker", name: "Tracker", editable: true }
];
const rows = [
{ r1: "data 1", status: "BLOCKED", tracker: "tracker 1" },
{ r1: "data 2", status: "PASS", tracker: "tracker 1" },
{ r1: "data 3", status: "ISSUE", tracker: "tracker 2" }
];
const [state, setState] = useState({ rows });
const onGridRowsUpdated = ({ fromRow, toRow, updated }) => {
setState((state) => {
const rows = state.rows.slice();
for (let i = fromRow; i <= toRow; i++) {
rows[i] = { ...rows[i], ...updated };
}
return { rows };
});
};
return (
<div>
<ReactDataGrid
columns={columns}
rows={state.rows}
rowsCount={3}
onGridRowsUpdated={onGridRowsUpdated}
enableCellSelect={true}
className="rdg-light"
/>
</div>
);
};
export default EntryCriteriaGrid;
import React, { Component } from "react";
import ReactDOM from "react-dom";
export default class DropdownCustomEditor extends Component {
constructor(props) {
super(props);
this.state = {
selected: ""
};
this.options = [
{ id: "blocked", value: "BLOCKED" },
{ id: "pass", value: "PASS" },
{ id: "issue", value: "ISSUE" },
{ id: "notStarted", value: "NOT STARTED" }
];
}
componentDidMount() {
if (this.props.row && this.props.row.status)
this.setState({ selected: this.props.row.status });
}
getValue = function () {
return { status: this.state.selected };
};
getInputNode() {
return ReactDOM.findDOMNode(this).getElementsByTagName("select")[0];
}
update(e) {
this.setState({ selected: e.target.value });
this.props.onRowChange({ ...this.props.row, status: e.target.value }, true);
}
render() {
return (
<select
className="rdg-select-editor"
onChange={(e) => this.update(e)}
autoFocus
value={this.state.selected}
>
{this.options.map((elem) => {
return (
<option key={elem.id} value={elem.value}>
{elem.value}
</option>
);
})}
</select>
);
}
}
Just change your code as follows:
In DropdownCustomEditor component:
update(e) {
this.setState({ selected: e.target.value });
this.props.onRowChange({ ...this.props.row, status: e.target.value });
}
In EntryCriteriaGrid component
const onGridRowsUpdated = (rows) => {
setState({ rows });
};
and
<ReactDataGrid
columns={columns}
rows={state.rows}
rowsCount={3}
//onRowsUpdate={onGridRowsUpdated}
enableCellSelect={true}
className="rdg-light"
onRowsChange={(rows) => onGridRowsUpdated(rows)}
/>

How to implement AddAdiditions in React Sematic UI using Hooks?

I want to have a drop down in my application which allows the user to add an item to the dropdown. I am using React Sematic UI.
Sematic UI Dropdown ALlowAdditions
I am new to react hooks and I want to know how I can implement the onChange and onAddition function using hooks.
import React, { Component } from 'react'
import { Dropdown } from 'semantic-ui-react'
const options = [
{ key: 'English', text: 'English', value: 'English' },
{ key: 'French', text: 'French', value: 'French' },
{ key: 'Spanish', text: 'Spanish', value: 'Spanish' },
{ key: 'German', text: 'German', value: 'German' },
{ key: 'Chinese', text: 'Chinese', value: 'Chinese' },
]
class DropdownExampleAllowAdditions extends Component {
state = { options }
handleAddition = (e, { value }) => {
this.setState((prevState) => ({
options: [{ text: value, value }, ...prevState.options],
}))
}
handleChange = (e, { value }) => this.setState({ currentValue: value })
render() {
const { currentValue } = this.state
return (
<Dropdown
options={this.state.options}
placeholder='Choose Language'
search
selection
fluid
allowAdditions
value={currentValue}
onAddItem={this.handleAddition}
onChange={this.handleChange}
/>
)
}
}
export default DropdownExampleAllowAdditions
Any help would be greatly appreciated. Thanks in advance :)
import React, { useState } from "react";
import { Dropdown } from "semantic-ui-react";
const options = [
{ key: "English", text: "English", value: "English" },
{ key: "French", text: "French", value: "French" },
{ key: "Spanish", text: "Spanish", value: "Spanish" },
{ key: "German", text: "German", value: "German" },
{ key: "Chinese", text: "Chinese", value: "Chinese" }
];
const DropDownWithHooks = () => {
const [dropDownOptions, setDropDownOptions] = useState(options);
const [currentValue, setCurrentValue] = useState("");
const handleAddition = (e, { value }) => {
setDropDownOptions((prevOptions) => [
{ text: value, value },
...prevOptions
]);
};
const handleChange = (e, { value }) => setCurrentValue(value);
return (
<Dropdown
options={dropDownOptions}
placeholder="Choose Language"
search
selection
fluid
allowAdditions
value={currentValue}
onAddItem={handleAddition}
onChange={handleChange}
/>
);
};
export default DropDownWithHooks;
Working Sandbox

Updating React-Select menu with setState?

I am trying to get React-Select to display a different dropdown menu list based on the user input:
const helpOptions = [
{ value: "user", label: "u:<String> User Operator" },
{ value: "day", label: "d:<Number> Date Operator" },
{ value: "week", label: "w:<Number> Week Operator" },
{ value: "month", label: "m:<Number> Month Operator" },
{ value: "bracket", label: "() Brackets Operator" },
{ value: "and", label: "&& AND Operator" },
{ value: "or", label: "|| OR Operator" },
{ value: "not", label: "~ NOT Operator" }
];
const userOptions = [
{ value: "john", label: "u:John" },
];
class Field extends Component {
state = {
menu: userOptions,
value: ""
};
onInputChange = e => {
if (e.substring(0, 1) === "?") {
this.setState(
{
menu: helpOptions,
value: e
},
() => {
console.log(this.state.menu);
}
);
} else {
this.setState({
menu: []
});
}
};
render() {
const { menu, value } = this.state;
console.log("rendering");
console.log(menu);
return (
<Select
isMulti
value={value}
options={menu}
onInputChange={this.onInputChange}
/>
);
}
}
The desired behavior is if the first character of the text entered into the search field is a '?' the menu will populate with the const of helpOptions. Otherwise it would be (for now) empty.
Codesandbox: https://codesandbox.io/s/runtime-sun-cfg71
From the console logs, I seem to be getting the values and the rendering seems to be working. However, I am still getting 'No Option' as a response from the React-Select component.
How can I dynamically change the React-Select menu items based on the user's input?
Update
If you want your state to update after calling setState you need use a function that will work only after updating the state:
this.setState(state => ({
...state,
menu: helpOptions
}));
First of all you need to call a constructor in your component. Secondly, in documentation to react-select prop value doesn't exist. Thirdly, it’s good practice to copy your state before changing.
Here is a valid code:
import React, { Component } from "react";
import Select from "react-select";
import "./styles.css";
const helpOptions = [
{ value: "user", label: "u:<String> User Operator" },
{ value: "day", label: "d:<Number> Date Operator" },
{ value: "week", label: "w:<Number> Week Operator" },
{ value: "month", label: "m:<Number> Month Operator" },
{ value: "bracket", label: "() Brackets Operator" },
{ value: "and", label: "&& AND Operator" },
{ value: "or", label: "|| OR Operator" },
{ value: "not", label: "~ NOT Operator" }
];
const userOptions = [
{ value: "john", label: "u:John" },
{ value: "stan", label: "d:Stan" },
{ value: "addison", label: "w:Addison" },
{ value: "dionis", label: "m:Dionis" }
];
class Field extends Component {
constructor(props) {
super(props);
this.state = {
menu: userOptions,
value: ""
};
}
onInputChange = e => {
if (e.substring(0, 1) === "?") {
console.log("help");
this.setState({
...this.state,
menu: helpOptions
});
} else {
this.setState({
...this.state,
menu: userOptions
});
}
};
render() {
const { menu, value } = this.state;
return <Select isMulti options={menu} onInputChange={this.onInputChange} />;
}
}
export default Field;
Here is an example on codesandbox.

How to configure multiple bars on same chart using react-charts

I have a react wherein I am able to display the. For this i am using react-charts library.
To populate chart data I am making a API call and thereafter updating the state. I want to display multiple values for YAxis.
My sample API response is:
{
"result": 1,
"data": [
{
"data1": "1272.00",
"data2": "1183.00",
"price": "131.00"
},
{
"data1": "1328.00",
"data2": "1468.00",
"price": "132.00"
},
{
"data1": "1829.00",
"data2": "1445.00",
"price": "133.00"
},
]
}
I want data1 and data2 values forYAxis and price for XAxis.
React code:
import React, { Component } from "react";
import Sidebar from "./Sidebar";
import { Chart } from "react-charts";
import axios from "axios";
const qs = require("qs");
class Home extends Component {
state = {
datelist: [],
chart_data: []
};
componentDidMount() {
this.getDatesList();
axios
.post(
`http://127.0.0.1:8000/pricedata/`,
qs.stringify({ date: "2019-01-11" })
)
.then(res => {
if (res.data.result === 1) {
this.setState({
chart_data: [
{
label: "Strike",
data: res.data.data.map(Object.values)
}
]
});
} else {
this.setState({ chart_data: [] });
}
});
}
getDatesList() {
axios.get("http://127.0.0.1:8000/dateslist/").then(res => {
if (res.data.result === 1) {
this.setState({ datelist: res.data.data });
} else {
this.setState({ datelist: [] });
}
});
}
handleChange = event => {
var dateval = event.target.value;
axios
.post(`http://127.0.0.1:8000/pricedata/`, qs.stringify({ date: dateval }))
.then(res => {
if (res.data.result === 1) {
this.setState({
chart_data: [
{
label: "Strike",
data: res.data.data.map(Object.values)
}
]
});
} else {
this.setState({ chart_data: [] });
}
});
};
render() {
return (
<div className="container container_padding">
<div className="row">
<Sidebar />
<div className="col-md-9 col-sm-9 col-xs-12">
<select
className="form-control"
style={{ width: "120px", marginBottom: "10px" }}
onChange={this.handleChange}
>
{this.state.datelist.map((date, i) => (
<option value={date} key={i}>
{date}
</option>
))}
</select>
<div
style={{
width: "400px",
height: "300px"
}}
>
<Chart
data={this.state.chart_data}
series={{ type: "bar" }}
axes={[
{ primary: true, type: "ordinal", position: "bottom" },
{ type: "linear", position: "left", stacked: true }
]}
primaryCursor
tooltip
/>
</div>
</div>
</div>
</div>
);
}
}
export default Home;
How can I achieve this?
Thanks in advance.
Modify following lines:
handleChange = event => {
var dateval = event.target.value;
axios
.post(`http://127.0.0.1:8000/pricedata/`, qs.stringify({ date: dateval }))
.then(res => {
if (res.data.result === 1) {
this.setState({
chart_data: [
{
label: "bar1",
data: res.data.data.map((d) => ({ x: d.price, y: d.data1 })
},
{
label: "bar2",
data: res.data.data.map((d) => ({ x: d.price, y: d.data2 })
}
]
});
} else {
this.setState({ chart_data: [] });
}
});
};
and inside render:
<Chart
data={this.state.chart_data}
series={{ type: 'bar' }}
axes={[
{ primary: true, position: 'bottom', type: 'ordinal' },
{ position: 'left', type: 'linear', min: 0 },
]}
primaryCursor
secondaryCursor
tooltip
/>

Resources