spread prevState with variable - javascript

I am trying to refactor a codebase and I got stuck somewhere. I am basically trying to update the state based on the onChange event of a select box.
In this case, my searchCriteria parameter in my handleFilterChange functions is ingredients.
But let's assume I have another select box that contains the options of anotherIngredients. I couldn't spread the prevState based on a variable.
I had to type ...prevState.ingredients
Is there a proper way to do that?
So my component state is:
state = {
ingredients: {
name: "",
operation: "",
value: ""
},
anotherIngredients: {
name: "",
operation: "",
value: ""
}
};
My handler is:
handleFilterChange = (event, searchCriteria, searchCriteriaKey) => {
let newValue = event.target.value;
this.setState(prevState => ({
[searchCriteria]: {
...prevState.ingredients,
[searchCriteriaKey]: newValue
}
}));
};
My Select box component is :
<Select
value={ingredients.name}
options={[
{ key: "", value: "Please choose an ingredient" },
{ key: "ingredient1", value: "INGREDIENT 1" },
{ key: "ingredient2", value: "INGREDIENT 2" },
{ key: "ingredient3", value: "INGREDIENT 3" },
{ key: "ingredient4", value: "INGREDIENT 4" }
]}
changeHandler={event =>
this.handleFilterChange(event, "ingredients", "name")
}
/>
Hope I could explain myself. Thank you!

You should reuse your variable searchCriteria to extract the previous values from the state.
handleFilterChange = (event, searchCriteria, searchCriteriaKey) => {
let newValue = event.target.value;
this.setState(prevState => ({
[searchCriteria]: {
...prevState[searchCriteria],
[searchCriteriaKey]: newValue
}
}));
};

Related

ReactJs with Ant-Design page is opened checkbox selected in Table

I am creating a React project with Ant-Design. When the page is opened, I want several checkboxes in the table to be selected.
Hook:
const [selectedPages, setSelectedPages] = useState([]);
RowSelection :
let rowSelectionPages = {
selectedPages,
onChange: onSelectPagesChange,
selections: [Table.SELECTION_ALL, Table.SELECTION_NONE],
getCheckboxProps: (record) => {
return {
disabled: record.screenName === 'Disabled',
name: record.screenName,
defaultChecked: record.key === 1
};
},
};
onSelectPagesChange:
let onSelectPagesChange = (newSelectedPages) => {
setSelectedPages(newSelectedPages);
};
Columns:
let columnsPages = [
{
title: "screen name",
dataIndex: "screenName",
render: (text) => <a>{text}</a>,
},
];
MyData:
let dataPages = [
{
key: "1",
screenName: "Home",
},
{
key: "2",
screenName: "Login",
},
{
key: "3",
screenName: "profile",
},
{
key: "4",
screenName: "Disabled",
},
];
Table:
<Table
rowSelection={{
type: "checkbox",
...rowSelectionPages,
}}
columns={columnsPages}
dataSource={dataPages}
/>
I am using Ant-Design library for the first time.
This is the code I tried.
But I couldn't come to a conclusion.
Add row indexes in the state selection
const [selectedPages, setSelectedPages] = useState([0]); // check first row
demo

How to get value of their object in react hooks array?

Good afternoon, I rarely write here. But now I really can't understand.
I am using React Select to display select. In the onChange attribute, I pass a function that forms the object and writes it to UseStat. But then I try to find an object using the find and
take an array of values from it.
const [selectedSpecificationValues, setSelectedSpecificationValues] = useState([])
const setSelectedSpecificationValuesHandler = (e, s) => {
const maybeSelectedSpecification = selectedSpecificationValues.find(
ss => ss._id === s._id
)
const objForWrite = {
_id: s._id,
name: s.name,
values: e,
}
if (maybeSelectedSpecification) {
const index = selectedSpecificationValues.indexOf(
maybeSelectedSpecification
)
let newArr = [...selectedSpecificationValues]
newArr[index] = objForWrite
setSelectedSpecificationValues(newArr)
} else {
setSelectedSpecificationValues([
...selectedSpecificationValues,
objForWrite,
])
}
}
const ssTestVal = Id => {
let result = []
if (selectedSpecificationValues.length > 0) {
const foundItem = selectedSpecificationValues.find(i => i._id === Id)
console.log(Id, foundItem)
if (foundItem) {
result = foundItem.values
}
}
return result
}
/* specifications = [
{
values: [
{
value: 0,
label: '480 min',
},
{
value: 1,
label: '120 min',
},
],
_id: '5fe74eae07905e53ebf263ec',
name: 'Duration',
slug: 'duration',
createdAt: '2020-12-26T14:54:38.362Z',
updatedAt: '2020-12-29T08:37:18.962Z',
__v: 1,
},
{
values: [
{
value: 0,
label: 'Photobook',
},
{
value: 1,
label: 'Photocard',
},
{
value: 2,
label: 'Album',
},
{
value: 3,
label: 'DVD',
},
{
value: 4,
label: 'Stickers',
},
{
value: 5,
label: 'CD',
},
],
_id: '5fe74e9107905e53ebf263eb',
name: 'Includes',
slug: 'includes',
createdAt: '2020-12-26T14:54:09.267Z',
updatedAt: '2020-12-26T16:10:16.283Z',
__v: 9,
},
] */
{
specifications &&
specifications.map((s, idx) => (
<Select
classNamePrefix='select2-selection'
options={s.values}
value={() => ssTestVal(s._id)}
onChange={e => setSelectedSpecificationValuesHandler(e, s)}
isMulti
/>
))
}
It is also important to understand that I loop a lot of selections in order to select different characteristics and their values.
I will be glad to help!
https://codesandbox.io/s/serverless-night-kez18?file=/src/App.js
Looks like minor issue with how you were computing the value for the sub-select inputs. You were defining it as though it were a callback.
<Select
classNamePrefix="select2-selection"
options={s.values}
value={() => ssTestVal(s._id)} // <-- not correct, not a callabck
onChange={(e) => setSelectedSpecificationValuesHandler(e, s)}
isMulti
/>
It should just be immediately invoked to compute and return an input's value.
<Select
classNamePrefix="select2-selection"
options={s.values}
value={ssTestVal(s._id)} // <-- invoke immediately for return value
onChange={(e) => setSelectedSpecificationValuesHandler(e, s)}
isMulti
/>

How do I use a variable from a Const in a useEffect hook? React JS

EDIT: Your solution worked but now my dropdown doesn't show what is selected unless its selected twice, like this:
Here I selected Health Care, but the dropdown still says "Select Industry"
The here I selected Health Care for a second time and it now shows that it is selected, this is happening with all of the dropdown options
I have a dropdown menu that I can select an option from, which saves the option to a variable. I want to use this variable to change the fetch route used in my useEffect hook so that the data found is filtered to a specific industry. How would I do this? Is there an easier way to filter the mapped data rather than changing the fetch address?
This is my code:
import React, {useState, useEffect} from "react";
import { AgGridReact } from "ag-grid-react";
import { Dropdown } from "semantic-ui-react";
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-balham.css";
// Data Table
export default function Table() {
const[rowData, setRowData] = useState([]);
const columns = [
{ headerName: "Name", field: "name", sortable: true},
{ headerName: "Symbol", field: "symbol", sortable: true},
{ headerName: "Industry", field: "industry", sortable: true},
];
const searchIndustry = (event, {value}) => {
let industryChoice = value;
// I want to use this variable
console.log(industryChoice);
}
const DropdownSearchSelection = () => (
<Dropdown
placeholder="Select Industry"
search
selection
options={industryOptions}
onChange={searchIndustry}
/>
);
useEffect(() => {
// To change this address
fetch(`http://131.181.190.87:3000/stocks/symbols${industryChoice}`)
.then(res => res.json())
.then(data =>
data.map(stock => {
return {
name: stock.name,
symbol: stock.symbol,
industry: stock.industry,
};
})
)
.then(stock => setRowData(stock));
}, []);
const industryOptions = [
{ key: "as", value: "", text: "View All Industries" },
{ key: "dc", value: "?industry=consumer%20discretionary", text: "Consumer Discretionary" },
{ key: "ds", value: "?industry=consumer%20staples", text: "Consumer Staples" },
{ key: "en", value: "?industry=energy", text: "Energy" },
{ key: "fi", value: "?industry=einancials", text: "Financials" },
{ key: "hc", value: "?industry=health%20care", text: "Health Care" },
{ key: "in", value: "?industry=industrials", text: "Industrials" },
{ key: "it", value: "?industry=information%20technology", text: "Information Technology" },
{ key: "ma", value: "?industry=materials", text: "Materials" },
{ key: "re", value: "?industry=real%20estate", text: "Real Estate" },
{ key: "ts", value: "?industry=telecommunication%20services", text: "Telecommunication Services" },
{ key: "ut", value: "?industry=utilities", text: "Utilities" },
];
return (
<div className="filter">
<div>
<input type="text" id="searchBox" placeholder="Filter..."/>
<DropdownSearchSelection />
<br/>
</div>
<div className="ag-theme-balham" >
<AgGridReact
columnDefs={columns}
rowData={rowData}
pagination={true}
paginationPageSize={11}
/>
</div>
</div>
);
}
Thanks for the help! :)
First, you will need to store the selected option from Dropdown into your component's state.
const[industryChoice, setIndustryChoice] = useState();
And on your searchIndustry method,
const searchIndustry = (event, {value}) => {
setIndustryChoice(value);
}
And then, you add searchIndustry as part of the dependency array, which will fetch the data based on the industryChoice state, and this will be triggered whenever the value of industryChoice is updated.
useEffect(() => {
// To change this address
fetch(`http://131.181.190.87:3000/stocks/symbols${industryChoice}`)
.then(res => res.json())
.then(data =>
data.map(stock => {
return {
name: stock.name,
symbol: stock.symbol,
industry: stock.industry,
};
})
)
.then(stock => setRowData(stock));
}, [industryChoice]);
As for the additional issue you have raised, you should bind the value of the industryChoice state to the Dropdown.
<Dropdown
placeholder="Select Industry"
search
selection
options={industryOptions}
onChange={searchIndustry}
value={industryChoice}
/>

How to update value in array of objects when onchange text is called (in flat list)

There is a state value
savedData: [
{ key: 'First Name', value: '' },
{ key: 'Last Name', value: '' },
{ key: 'Mobile', value: '' },
{ key: 'Email', value: '' },
{ key: 'Password', value: '' },
{ key: 'Forgot Password', value: '' },
{ key: 'CheckBox1', value: '' },
]
Text inputs are in a flat list, each text input is rendered in each cell.
How can I update a value in the array by index when onChange of text input is called, without using state variables or global variables?
You could pass the key as parameter for onChange method
onChange={() => this.handleChange("First Name")}
and then just update the value.
let field = savedDate.find(({key}) => key == key_param);
field.value = ...
I'd recommend to use the field's id as key for the savedData state and just pass the event.target.id as parameter.
savedData:[
{key:'firstName',value:''},
{key:'lastName',value:''},
{key:'mobile',value:''},
{key:'email',value:''},
{key:'password',value:''},
{key:'forgot Password',value:''},
{key:'checkBox1',value:''},
]
...............
onChange={(e) => this.handleChange(e.target.id)}

Filters in VueJs

I'm trying to build a small application in Vuejs 2.0, where I'm using v-select component, I'm having a data format something like this:
{
"model":
[
{
"id":1,
"salutation":"Mr",
"first_name":"Rahul",
"last_name":"Bashisht",
"number":"9876521102",
"email":"rahul#icicibank.com",
"company":
{
"id":1,
"name":"ICICI Bank",
"is_client":1,
}
},
{
"id":2,
"salutation":"Mr",
"first_name":"Vikash",
"last_name":"Pandey",
"number":"0987654345",
"email":"vikash#hdfc.com",
"company":
{
"id":2,
"name":"HDFC Bank",
"is_client":0,
}
}
]
}
Now I'm setting this to a variable model and then trying to filter with client = 1 in computed property something like this:
contactClients: function() {
if(this.model)
{
return this.model
.filter(f => (f.company.is_client == 1))
.map(d => ({label: d.first_name+' '+d.last_name+' - '+d.company.name, value: d.id}))
}
},
Then I'm placing it in v-select options as:
<v-select multiple :options="contactClients" v-model="clientParticipants"></v-select>
Now I'm having a other v-select which is in accordance with company name but is_client is true, so I'm trying something like this:
I've data set of companies:
{
"model":
[
{
"id":1,
"name":"ICICI Bank",
"is_client":1,
},
{
"id":2,
"name":"HDFC Bank",
"is_client": 0,
},
{
"id":3,
"name":"BNP Paribas",
"is_client": 0,
}
{
"id":4,
"name":"Barclays Bank",
"is_client": 1,
}
]
}
I'm placing it in companies variable and filtering it something like this:
clients: function () {
if(this.companies)
{
return this.companies
.filter(f => f.is_client == 1)
.map(d => ({label: d.name, value: d.id}))
}
}
And in v-select I'm having:
<v-select :options="clients" v-model="summary.client"></v-select>
I want to have an extra filter in accordance to the selection of contactsClients, i.e. if any contactsClients are being selected in the first list, second list should have only those company as option and if there is no selection in first list(contactClients) then second list should have all default options with simple is_client filter which is in current situation. Since the selection in contactClients is multiple so I don't know how to filter elements. Please guide me.
Edit: Codepen Link
May be this will help you.
contactClients: function() {
if (this.model) {
return this.model.filter(f => f.company.is_client == 1).map(d => ({
label: d.first_name + " " + d.last_name + " - " + d.company.name,
value: d.id,
companyId: d.company.id
}));
}
},
clients: function() {
var self = this;
var res = [];
if (this.companies) {
if (this.clientParticipants.length) {
console.log(this.clientParticipants)
this.clientParticipants.forEach(function(cc) {
self.companies.forEach(function(c) {
if (cc.companyId === c.id) {
res.push(c);
}
});
});
return res.map(d => ({ label: d.name, value: d.id }));
} else {
return this.companies
.filter(f => f.is_client == 1)
.map(d => ({ label: d.name, value: d.id }));
}
}
}
example here
You could use a computed property to implement your filter logic there and bind it to your second list.
Ref.: https://v2.vuejs.org/v2/guide/computed.html#Computed-Properties

Categories

Resources