Using state in method - React - reactjs

I've got a method called devCreateSteps and I want to use state in that but it throws an error saying;
Uncaught TypeError: Cannot read property 'isTemplateUsed' of undefined
Here's the snippet of my code;
constructor() {
super();
this.state = {
modalVisible: false,
tableLoading: false,
modalHeader: "",
isTemplateUsed: false
};
}
devCreateSteps = [{
title: 'Info',
content: (<StepOne isTemplateUsed={this.state.isTemplateUsed} />),
}, {
title: 'Device',
content: (<StepTwo />),
}, {
title: 'Location',
content: (<StepThree />),
},
{
title: 'Properties',
content: (<StepFour />),
},
{
title: 'Controls',
content: (<StepFive />),
},
{
title: 'Summary',
content: (<StepFinal />),
}];
The problem is I can't use
isTemplateUsed={this.state.isTemplateUsed}
this in the devCreateSteps
What is the right way to use state to send it as props ?

Instead of defining devCreateSteps as a class property directly in class, do it in the componentWillMount function.
class App extends React.Component {
constructor() {
super();
this.state = {
modalVisible: false,
tableLoading: false,
modalHeader: "",
isTemplateUsed: false
};
}
componentWillMount() {
this.devCreateSteps = [{
title: 'Info',
content: (<StepOne isTemplateUsed={this.state.isTemplateUsed} />),
}, {
title: 'Device',
content: (<StepTwo />),
}, {
title: 'Location',
content: (<StepThree />),
},
{
title: 'Properties',
content: (<StepFour />),
},
{
title: 'Controls',
content: (<StepFive />),
},
{
title: 'Summary',
content: (<StepFinal />),
}];
}
}
Also define state as a property intializer too.
class App extends React.Component {
state = {
modalVisible: false,
tableLoading: false,
modalHeader: "",
isTemplateUsed: false
};
devCreateSteps = [{
title: 'Info',
content: (<StepOne isTemplateUsed={this.state.isTemplateUsed} />),
}, {
title: 'Device',
content: (<StepTwo />),
}, {
title: 'Location',
content: (<StepThree />),
},
{
title: 'Properties',
content: (<StepFour />),
},
{
title: 'Controls',
content: (<StepFive />),
},
{
title: 'Summary',
content: (<StepFinal />),
}];
}
P.S. make sure you have stage-2 added as a preset to babel in you
webpack config, since property initializers are not part of ES6.

Uncaught TypeError: Cannot read property 'isTemplateUsed' of undefined
Because you are using state variable named open before initializing , you can avoid this error by two ways either
try to initialize variable with empty array and then assign values using state wihtin constructor.
devCreateSteps: [];
constructor(props, state) {
super(props, state);
this.state = {
open: this.props.open
}
console.log(this.props, this.state);
this.devCreateSteps = [{
title: 'Info',
content: (<p isTemplateUsed={this.state.open} />)
}]
}
or you can use componentWillMount as suggested in above answer.

Related

Objects are not valid as a React child error in React Datatable

OK, so Im getting this error when trying to return some data from my web api. Ive tried all as suggested on other similar posts but cant get this working. Any help appreciated.
Objects are not valid as a React child. If you meant to render a collection of children, use an array instead.
clg(records) returns this:
[{
id:1,
Listing: {id: 2, title: 'Testtt'},
ListingId: 2
},
{
id:2,
Listing: {id: 3, title: 'hell world'},
ListingId: 3
}]
here is my reactjs code:
class Products extends Component {
constructor(props) {
super(props);
this.columns = [
{
key: "id",
text: "Id",
className: "id",
align: "left",
sortable: true,
},
{
id:"ListingId"
text: "Merchant ID",
className: "name",
align: "left",
sortable: true,
},
}
];
this.state = {
records: []
};
this.getData = this.getData.bind(this);
}
componentDidMount() {
this.getData()
};
componentWillReceiveProps(nextProps) {
this.getData()
}
getData() {
axios
.get("/api/products")
.then(res => {
this.setState({ records: res.data})
})
.catch()
}
render() {
const {records}=this.state;
console.log(records);
return (
<div>
<ReactDatatable
records={this.state.records}
columns={this.columns}
loading='true'
/>
</div>
);
}}
Currently its displaying ListingId in the column, how can i display the Listing title instead?
i am currently using this package :
https://www.npmjs.com/package/#ashvin27/react-datatable
Here is the solution to my question
{
key:'ListingId',
text: "Column Title",
className: "name",
align: "left",
sortable: true,
cell: record => {
console.log(record)
return (
<span>{record.Listing.title}</span>)
}
},

How can I display the current value from a chart?

I am new to React and I work on a small project basically, I have a chart and I just want to display the current value from the chart.
For example, I have a chart with 4 random values:[5,2,5,1], so I want to have displayed the current value below the chart like first is 5, second is 2 and so on.
Here is my part of code:
class App extends React.Component {
addPoint = (point) => {
currentData = this.state.options.series[0].data
this.setState({
options: {
series: [
{ data: [...currentData, point]}
]
}
});
}
constructor(props) {
super(props);
this.internalChart = undefined;
this.dataStream = new DataStream();
this.dataStream.setUpdateCallback(this.addPoint);
this.state = {
options: {
chart: {
events: {
load: function () {
}
}
},
time: {
useUTC: false
},
rangeSelector: {
buttons: [{
count: 1,
type: 'minute',
text: '1M'
}, {
count: 5,
type: 'minute',
text: '5M'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 2
},
title: {
text: 'Live random data'
},
exporting: {
enabled: false
},
series: [{
name: 'Random data',
data: [[(new Date()).getTime(), 0]]
}]
}
};
}
render() {
return (
<HighchartsReact
constructorType={"stockChart"}
highcharts={Highcharts}
options={this.state.options}
/>
);
}}
Based on your snippet code, try to make random method by using function
Math.floor(Math.random() * Math.floor(max))
And then assign the options to HighchartsReact,
Full code on sandbox: https://codesandbox.io/s/headless-dream-0lzj1

Cannot change hidden column state from true to false on setState

I'm using devexpress React table and you can hide and show columns via state.
I would like to change the state for hidden from true to false but I get an Uncaught Invariant Violation error.
I've tried to use setState but doesn't work.
class ResultsTable extends Component {
constructor(props) {
super(props);
this.state = {
columns: [
{ name: 'agent', title: 'Agent' },
{ name: 'alertGroup', title: 'Alert Group', hidden:true },
{ name: 'manager', title: 'Manager', hidden:true }
],
};
}
componentDidMount() {
this.testAlert();
}
testAlert = () => {
if (this.props.alertgroupColumn()) {
this.setState({
columns: [{ name: 'alertGroup', title: 'Alert Group', hidden:false }]
})
}
}
Hidden should change from true to false.
I have another alternative to update your state
class ResultsTable extends Component {
constructor(props) {
super(props);
this.state = {
columns: [
{ name: 'agent', title: 'Agent' },
{ name: 'alertGroup', title: 'Alert Group', hidden:true },
{ name: 'manager', title: 'Manager', hidden:true }
],
};
}
componentDidMount() {
this.testAlert();
}
testAlert = () => {
if (this.props.alertgroupColumn()) {
//---- get the columns from state
let columns = JSON.parse(JSON.stringify(this.state.columns))
columns[1].hidden = false
this.setState({
columns:columns
})
this.setState({
columns: [{ name: 'alertGroup', title: 'Alert Group', hidden:false }]
})
}
}

Use destructuring assignment inside state

class BottomPanelProgramTabs extends React.Component<Props, State> {
state = {
activeTab: this.props.children[0].props.label,
};
...
ESLint want me to use destructuring assignment on
this.props.children[0].props.label
any ideas on how to do that?
you can do like this.
For more reference about prefer-destructuring
class BottomPanelProgramTabs extends React.Component<Props, State> {
constructor(){
let [props] = this.props.children;
state = {
activeTab : props.label
}
}
class BottomPanelProgramTabs extends React.Component<Props, State> {
state = {
activeTab: 'default label'
};
componentDidMount = () => {
const [{ props: { label } }] = this.props.children;
this.setState({
activeTab: label || 'default label',
...
})
}
...
You can mix destructing by getting the first element with [] and get the props with {}.
For example:
using [child] will give us the first element in the array.
const children = [{
props: {
label: 'Some label'
}
},
{
props: {
label: 'Second label'
}
},
,
{
props: {
label: 'another label'
}
}]
const [child] = children;
console.log(child);
to get props we can continue mixing our destruction by adding [ {props} ] which returns props object.
const children = [{
props: {
label: 'Some label'
}
},
{
props: {
label: 'Second label'
}
},
,
{
props: {
label: 'another label'
}
}]
const [ {props} ] = children;
console.log(props);
to get the label from props will can do this [{ props: { label } }]
const children = [{
props: {
label: 'Some label'
}
},
{
props: {
label: 'Second label'
}
},
,
{
props: {
label: 'another label'
}
}]
const [{ props: { label } }] = children;
console.log(label);
With complex data
const children = [{
props: {
label: [{
data: {
title: 'complex destructor'
}
},
{
data: {
title: 'complex destructor 2'
}
}]
}
},
{
props: {
label: 'Second label'
}
},
,
{
props: {
label: 'another label'
}
}]
const [{ props: { label: [ { data: { title } } ] } }] = children;
console.log(title)

Highcharts not rendering : React+Typescript+Highcharts

Trying to bring up a highchart using react. I am having multiple fetch api calls(for illustration, I have added only 2) whose data I will be using to render something in the UI.
In this example data1 is used to render a table, data2 is used to render a highchart.
I am storing the outputs of these calls in a state object. When I am calling these API's, I am getting the data but unable to set it to "series" property of highcharts for rendering, as a result nothing is getting rendered.
Structure of the data I am fetching
"api2" : [
{
"name" : "Test1",
"value" : 12
},
{
"name" : "Test2",
"value" : 9
}
]
Can someone help me with this? Where am I going wrong?
I am using highcharts-react-official for this
Code
import * as React from 'react';
import Highcharts from 'highcharts'
import HighchartsReact from 'highcharts-react-official';
interface IState {
data1: [];
data2: [];
}
interface IProps {}
class Example extends React.Component<IProps,IState> {
constructor(props:any)
{
super(props);
this.state = {
data1: [],
data2: []
}
}
componentDidMount()
{
Promise.all([
fetch('http://localhost:3001/api1'),
fetch('http://localhost:3001/api2')
])
.then(([res1, res2]) => Promise.all([res1.json(), res2.json()]))
.then(([data1, data2]) => this.setState({
data1: data1,
data2: data2
}));
}
render() {
let options:any;
options = {
chart: {
type: 'column'
},
credits: false,
exporting: {enabled: false},
title: {
text: ''
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'bottom'
},
xAxis: {
visible:false
},
yAxis: {
visible:false
},
plotOptions: {
column: {
dataLabels: {
enabled: true }
}
},
series: this.state.data2
};
return(
<div className="an-content">
//some table rendering will happen here
<HighchartsReact
highcharts={Highcharts}
options={options}
/>
</div>
)
}
}
export default Example;
You need to provide the data format required by Highcharts:
this.setState({
data2: data2.map(x => ({ name: x.name, data: [x.value] }))
});
Live demo: https://codesandbox.io/s/7w2pw4p900
API Reference: https://api.highcharts.com/highcharts/series.column.data

Resources