ReactJs Updating state of similar property value - arrays

I have two variable a and b in state. which are both copied one constant variable.(all are nested array).
Whenever i try to update a, it update b also, i dont know what the problem?
See The codesandbox demo: https://codesandbox.io/s/busy-maxwell-xvu5w
Code:
import React from "react";
const filterAttributes = [
{
name: "gender",
searchable: false,
search: "",
values: ["Male", "Female", "Child", "Other"]
},
{
name: "size",
searchable: false,
search: "",
values: ["30", "35", "15", "55", "10"]
},
{
name: "brand",
searchable: true,
search: "",
values: [
"Amazon",
"Flipkart",
"Apple",
"Vivo",
"Oppo",
"Samsung",
"Twitter"
]
}
];
export default class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
a: [...filterAttributes],
b: [...filterAttributes]
};
}
changeA = () => {
let a = [...filterAttributes];
a[0].search = "d-1--d";
this.setState({ a: [...a] });
};
render() {
return (
<div>
<pre style={{ maxWidth: "100%", overflowX: "scroll" }}>
<div>A: {JSON.stringify(this.state.a)}</div>
<hr />
<div>B: {JSON.stringify(this.state.b)}</div>
</pre>
<button onClick={this.changeA}>Change A</button>
<button>Change B</button>
</div>
);
}
}

let a = this.state.a;
a[0] = { ...a[0], ...{ search: "3-1--d" } };
this.setState({ a });
Using the spread operator we can make a copy of the object as well. Since this only shallow clones, it will only go one level deep.

The spread operator only goes one level deep (Shallow Copying).This means that the objects in your array are still referenced. I would recommend using lodash for deep copies but also a custom way like this works:
this.state = {
a: JSON.parse(JSON.stringify(filterAttributes)),
b: JSON.parse(JSON.stringify(filterAttributes))
};

Related

How to update nested array and objects in react

I'm trying to update the state in react. However, still not clear how shall I do it. The nested structure is something like :
this.state ={
permissionsObject:{
fruitsGroup:[
{
index:0,
taste:false,
color:false,
},
{
index:1,
taste:false,
color:false,
},
],
fruitsGroup:[
{
index:0,
taste:false,
color:false,
},
{
index:1,
taste:false,
color:false,
},
]
}
}
Now, if I want to update the value of fruitsGroup -> taste based on the index value then how shall I proceed. I found there are various solutions exists for nested structure. However, none of them were answering my query or they are using react hooks while I'm not. Thanks well in advance.
Edit: The fruitGroup will have different name. So, how can I even locate it dynamically while setting the state.
You can do it like this:
import React, { Component } from "react";
export class App extends Component {
state = {
permissionsObject: {
fruitsGroup: [
{
index: 0,
taste: false,
color: false,
},
{
index: 1,
taste: false,
color: false,
},
],
groupName: [
{
index: 0,
taste: false,
color: false,
},
{
index: 1,
taste: false,
color: false,
},
],
},
};
updateStateHandler = (idx) => {
const updatedFruitsGroup = this.state.permissionsObject.fruitsGroup.map(
(item) => (item.index === idx ? { ...item, taste: true } : item)
);
const newState = {
permissionsObject: {
...this.state.permissionsObject,
fruitsGroup: updatedFruitsGroup,
},
};
this.setState(newState);
};
render() {
return (
<div>
{JSON.stringify(this.state)}
<button onClick={() => this.updateStateHandler(0)}>
Update index 0
</button>
<button onClick={() => this.updateStateHandler(1)}>
Update index 1
</button>
</div>
);
}
}
export default App;

react-select-search does not allow me to select multiple values

I cannot select multiple values without holding Cmd key
My usage of SelectSearch in the component
<SelectSearch search multiple emptyMessage="Cannot find class" options={this.state.lessonSelections}
placeholder="Class" closeOnSelect={false} printOptions="on-focus"
className='select-search' onChange={this.handleLessonsChange.bind(this)} />
My handleLessonsChange
handleLessonsChange(value, state, props) {
this.setState({
lessons: state
});
}
and then the state
this.state = {
studentSelections: [],
lessonSelections: [],
materialSelections: [],
student: '',
lessons: [],
materials: [],
data: {},
};
I'm just lost on how I can select multiple values like how it is in the storybook
Try to set multiple option to true, it's in the docs https://www.npmjs.com/package/react-select-search. Like this:
export default function App() {
const options = [
{ name: "Swedish", value: "sv" },
{ name: "English", value: "en" },
{ name: "Spanish", value: "sp" }
];
return (
<div className="App">
<SelectSearch
options={options}
value="sv"
name="language"
placeholder="Choose your language"
multiple="true"
/>
</div>
);
}

Ant Design for React : Show/Hide particular column

I need a bit of help here, In an Ant Design table, I need to hide/show a particular column of a table depending on a state value. In the given sandbox link, I need to hide the surname column whenever the switch is Off and show when the switch is On.
Please, someone, look into this, and help me out.
Reference: https://codesandbox.io/s/purple-sun-1rtz1?file=/index.js
There is a working code, but it should be more customize, interactivize, and refactorize depending on your need:
// You can also modify the data in the `handleChnage`
// Or conditionally display it like here:
class EditableTable extends React.Component {
state = {
surNameShow: false
};
constructor(props) {
super(props);
this.columns = [
{
title: "Name",
dataIndex: "name",
width: "30%"
},
{
title: "Surname",
dataIndex: "surname",
width: "30%"
}
];
this.state = {
dataSource: [
{
key: "0",
name: "Edward 1",
surname: "King 1"
},
{
key: "1",
name: "Edward 2",
surname: "King 2"
}
]
};
}
handleChnage = key => {
this.setState({ surNameShow: !this.state.surNameShow }, () => {
console.log(this.state.surNameShow);
});
};
render() {
const { dataSource } = this.state;
const columns = this.columns;
return (
<div>
<p className="mr-3"> Show surname</p>
<Switch onChange={() => this.handleChnage()} />
<Table
bordered
dataSource={dataSource}
columns={
this.state.surNameShow
? columns
: columns.filter(ea => ea.dataIndex !== "surname")
}
pagination={false}
/>
</div>
);
}
}
ReactDOM.render(<EditableTable />, document.getElementById("container"));

How to get value from array, which is inside objects in react js?

I'm trying to get values from an array,
which is inside of objects:
const post = {
sticky: false,
template: "",
format: "standard",
_embedded: {
author: [{
0: {
id: 2,
name: "Charlie"
}
}],
term: ""
}
}
I need to get value of author.name, how should I map through this?
I tried this in my return:
return(
<div className={className}>
<h2>
{post._embedded.author[0].name}
</h2>
</div>
)
But it's not working, I get an error Cannot read property 'author' of undefine.
Sorry for silly question, but it's hard for me to understand.
This should work
post._embedded.author[0]['0'].name
You can try it out using the below snippet.
const post = {
sticky: false,
template: "",
format: "standard",
_embedded: {
author: [{
0: {
id: 2,
name: "Charlie"
}
}],
term: ""
}
};
const name = post._embedded.author[0]['0'].name;
console.log(name)
So the jsx would be
return(
<div className={className}>
<h2>
{post._embedded.author[0]['0'].name}
</h2>
</div>
)

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