How to execute useState dynamically from strings in react hooks? - reactjs

I have an object
const configs = [
{
label: 'Title',
name: 'Title',
value: titleToString,
field: SinglelineTextfield,
uniqueIdentifier: 0,
stateVar: 'criticalObjectTitle',
setStateVar: 'setCriticalObjectTitle',
},
{
name: 'type',
uniqueIdentifier: 1,
label: 'type',
value: typeToString,
field: SinglelineTextfield,
stateVar: 'criticalObjectType',
setStateVar: 'setCriticalObjectType',
},
{
name: 'Domain',
label: 'Domain',
value: domainToString,
field: SinglelineTextfield,
uniqueIdentifier: 2,
stateVar: 'criticalObjectDomainName',
setStateVar: 'setCriticalObjectDomainName',
}
]
I am retrieving the setState Variable wwwith the setFindVal in my onChange
const onChange = async (e) => {
const name = e.target.name || e.target.getAttribute('name')
const value = e.target.innertext ? e.target.innertext
: e.target.value
const setFindVal = configs.find(config => config.name === name).setStateVar
setFindVal(value)
console.log(setFindVal(value));
}
However, when I want to use setFindVal as a useState hook, it tells me that setFindVal is not defined..When I log setFindVal and its property type i get its a string, so I have created a useState hook outside of my function, however this still does not work. How do I convert a string into a useState function?
Error:
Uncaught (in promise) TypeError: setFindVal is not a function
Full code:
const editCriticalObjects = props => {
const query = new URLSearchParams(props.location.search)
const criticalObjectsId = query.get('id')
const loading = useContext(LoadingContext)
const user = useContext(UserContext)
const testing = useContext(TestingFrameworkContext)
const [editCriticalObjects, setEditCriticalObjects] = useState(null)
const [findval, setFindVal] = useState(null)
const [criticalObjectTitle, setCriticalObjectTitle] = useState(null)
const [criticalObjectDomainName, setCriticalObjectDomainName] = useState(null)
useEffect(() => {
async function onLoadCriticalObjects() {
loading.setLoading(true)
const results = await get(`get_critical_objects?id=${criticalObjectsId}`, user.user)
setEditCriticalObjects(results)
loading.setLoading(false)
}
onLoadCriticalObjects()
}, [])
const assetIdObject = editCriticalObjects && editCriticalObjects.filter(obj => {
if (obj.asset_id === criticalObjectsId )
return obj
})
console.log(assetIdObject);
const title = assetIdObject && assetIdObject.map(item => item.asset_id)
console.log(titleToString);
const titleToString = title && title.join(', ')
const domain = assetIdObject && assetIdObject.map(item => item.Domains.toString())
const domainToString = domain && domain.join(', ')
const type = assetIdObject && assetIdObject.map(item => item.type.toString())
const typeToString = type && type.join(', ')
const configs = [
{
label: 'Title',
name: 'Title',
value: titleToString,
field: SinglelineTextfield,
uniqueIdentifier: 0,
stateVar: 'criticalObjectTitle',
setStateVar: 'setCriticalObjectTitle',
},
{
name: 'type',
uniqueIdentifier: 1,
label: 'type',
value: typeToString,
field: SinglelineTextfield,
stateVar: 'criticalObjectType',
setStateVar: 'setCriticalObjectType',
},
{
name: 'Domain',
label: 'Domain',
value: domainToString,
field: SinglelineTextfield,
uniqueIdentifier: 2,
stateVar: 'criticalObjectDomainName',
setStateVar: 'setCriticalObjectDomainName',
}
]
const getObjectParams = {
asset_ids: criticalObjectTitle,
asset: true,
merge: true,
}
const onChange = async (e) => {
const name = e.target.name || e.target.getAttribute('name')
const value = e.target.innertext ? e.target.innertext
: e.target.value
const setFindVal = configs.find(config => config.name === name).setStateVar
setFindVal(value)
console.log(setFindVal(value));
}
const onClick = async () => {
loading.setLoading(true)
const results = await verifiedPost('post_critical_objects', testing.getObjectParams, user.user)
loading.setLoading(false)
console.log(getObjectParams);
}
return (!editCriticalObjects ? null :
<React.Fragment>
<PageWrapper title='Edit Critical Objects:'>
<div className='Main Card editCriticalObjectFormWrapper'>
{configs.map((config, k)=> {
const Field = config.field
return (
<React.Fragment key={config.name} >
<Field
style={{ marginBottom: '15px'}}
name={config.name}
placeholder={config.name}
value={config.stateVar}
initialValue={config.stateVar}
initialValues={config.stateVar}
uniqueIdentifier={k}
label={config.label}
onChange={onChange}
/>
</React.Fragment>
)
})}
<Button
className='Button Ghost Approve'
text='Submit'
onClick={onClick}
/>
</div>
</PageWrapper>
</React.Fragment>
)
}
export default editCriticalObjects
logging one value
new onchange:
const onChange = async (e) => {
const name = e.target.name || e.target.getAttribute('name')
const value = e.target.innertext ? e.target.innertext
: e.target.value
const setFindVal = configs.find(config => config.name === name).setStateVar;
setStateValues[setFindVal](value);
console.log(setFindVal, value);
}

The reason your getting it's not a function is because you are just using the value from the configs object which is a string.
You should assign the function as the value in config
const configs = [
{
...
setStateVar: setCriticalObjectTitle,
},
{
...
setStateVar: setCriticalObjectType,
},
{
...
setStateVar: setCriticalObjectDomainName,
}
];

Related

react-checkbox-tree not checked with children issue

I am using react checkbox tree package. I have a treeview with checkbox as below.
const nodes = [
{
value: "mars",
label: "Mars",
children: [
{
value: "phobos",
label: "Phobos"
},
{ value: "deimos", label: "Deimos" }
]
},
{
value: "saturn",
label: "Satrun"
},
{
value: "jupitor",
label: "Jupitor"
}
];
function Widget() {
const [checked, setChecked] = useState([]);
const [expanded, setExpanded] = useState([]);
const updateCheckedState = (node) => {
const childValues = [];
const isParent = node.isParent;
const updatedValues = isParent ? childValues : [node.value];
if (node.checked) {
setChecked([...updatedValues]);
} else {
const filteredChecks = checked.filter((check) => {
return !updatedValues.includes(check);
});
setChecked(filteredChecks);
}
};
return (
<CheckboxTree
iconsClass="fa5"
nodes={nodes}
checked={checked}
expanded={expanded}
onCheck={(nodes, node) => {
updateCheckedState(node);
}}
onExpand={(expanded) => setExpanded(expanded)}
/>
);
}
Full example is here
My issue is when I clicked checkbox with children it doesn't checked(example Mars). But I clicked no children element then it checked. Please help me to fix this.
checked is the array of node values, so you will need to assign the children's values.
const updatedValues = isParent
? node.children.map((v) => v.value)
: [node.value];

Ant design Transform component extracting selected data

I need to extract selected/filtered data into the state. I tried everything with onChange and on select change but only I got is the ID of one specific item.
ex. extracted_data = [ '1','2','3'....]
But I need a complete Item with id, name, price, etc...
I am passing data as source data, and after selecting I want to send in the parent component because I need to send it on the server.
Code is below
import { Table, Transfer } from "antd";
import difference from "lodash/difference";
import React, { useState } from "react";
// Customize Table Transfer
const TableTransfer = ({ leftColumns, rightColumns, ...restProps }) => (
<Transfer {...restProps}>
{({
direction,
filteredItems,
onItemSelectAll,
onItemSelect,
selectedKeys: listSelectedKeys,
disabled: listDisabled,
}) => {
const columns = direction === "left" ? leftColumns : rightColumns;
const rowSelection = {
getCheckboxProps: (item) => ({
disabled: listDisabled || item.disabled,
}),
onSelectAll(selected, selectedRows) {
const treeSelectedKeys = selectedRows
.filter((item) => !item.disabled)
.map(({ key }) => key);
const diffKeys = selected
? difference(treeSelectedKeys, listSelectedKeys)
: difference(listSelectedKeys, treeSelectedKeys);
onItemSelectAll(diffKeys, selected);
},
onSelect({ key }, selected) {
onItemSelect(key, selected);
},
selectedRowKeys: listSelectedKeys,
};
return (
<Table
rowSelection={rowSelection}
columns={columns}
dataSource={filteredItems}
size="small"
style={{
pointerEvents: listDisabled ? "none" : undefined,
}}
onRow={({ key, disabled: itemDisabled }) => ({
onClick: () => {
if (itemDisabled || listDisabled) return;
onItemSelect(key, !listSelectedKeys.includes(key));
},
})}
/>
);
}}
</Transfer>
);
const leftTableColumns = [
{
dataIndex: "name",
title: "Name",
},
{
dataIndex: "price",
title: "Price (€)",
},
{
dataIndex: "discount",
title: "Discount (%)",
},
];
const rightTableColumns = [
{
dataIndex: "name",
title: "Name",
},
{
dataIndex: "price",
title: "Price",
},
];
const App = ({ data, func }) => {
const mockData = data.map((item) => ({
key: item.id.toString(),
name: item.name,
price: item.price,
discount: item.discount,
}));
const originTargetKeys = mockData.map((item) => item.key);
const [targetKeys, setTargetKeys] = useState(originTargetKeys);
const [selected, setSelected] = useState([]);
const onSelectChange = (e) => {
setSelected(e);
};
const onChange = (e) => {
setTargetKeys(e);
func(selected);
};
return (
<>
<TableTransfer
dataSource={mockData}
targetKeys={targetKeys}
disabled={false}
showSearch={true}
onChange={onChange}
onSelectChange={onSelectChange}
filterOption={(inputValue, item) =>
item.name.indexOf(inputValue) !== -1
}
leftColumns={leftTableColumns}
rightColumns={rightTableColumns}
/>
</>
);
};
export default App;

Howcome form value does not reset?

I have a form.
This returns back and loads its value which is correct,
however when I start typing it only returns its value plus one letter from the onChange.
here is what I mean
How do I clear the value of the form when the onChange is executed? I have tried clearing the form using config.setStateVar('') which still does not seem to work. Does anyone have any ideas?
const onChange = (e, config) => {
config.setStateVar('')
const value = e.target.innertext ? e.target.innertext
: e.target.value
config.setStateVar(value)
}
Full Code:
const editCriticalObjects = props => {
const query = new URLSearchParams(props.location.search)
const criticalObjectsId = query.get('id')
const loading = useContext(LoadingContext)
const user = useContext(UserContext)
const [editCriticalObjects, setEditCriticalObjects] = useState([])
const [criticalObjectTitle, setCriticalObjectTitle] = useState('')
const [criticalObjectDomainName, setCriticalObjectDomainName] = useState('')
const [criticalObjectType, setCriticalObjectType] = useState('')
const [findVal, setFindVal] = useState('')
useEffect(() => {
async function onLoadCriticalObjects() {
loading.setLoading(true)
const results = await get(`get_critical_objects?id=${criticalObjectsId}`, user.user)
setEditCriticalObjects(results)
loading.setLoading(false)
}
onLoadCriticalObjects()
}, [])
const assetIdObject = editCriticalObjects.filter(obj => {
if (obj.asset_id === criticalObjectsId) {
return obj
}
return assetIdObject
})
const configs = [
{
label: 'Title',
name: 'Title',
value: assetIdObject.map(item => item.asset_id),
field: SinglelineTextfield,
uniqueIdentifier: 0,
stateVar: criticalObjectTitle,
setStateVar: setCriticalObjectTitle,
},
{
name: 'type',
uniqueIdentifier: 1,
label: 'type',
value: assetIdObject.map(item => item.type),
field: SinglelineTextfield,
stateVar: criticalObjectType,
setStateVar: setCriticalObjectType,
},
{
name: 'Domain',
label: 'Domain',
value: assetIdObject.map(item => item.Domains),
field: SinglelineTextfield,
uniqueIdentifier: 2,
stateVar: criticalObjectDomainName,
setStateVar: setCriticalObjectDomainName,
}
]
const criticalObjectParams = {
asset_ids: criticalObjectTitle,
asset: true,
merge: true,
}
console.log(criticalObjectParams)
const onChange = (e, config) => {
const value = e.target.innertext ? e.target.innertext
: e.target.value
config.setStateVar(value)
}
const onSubmitClick = async () => {
loading.setLoading(true)
await verifiedPost('post_critical_objects', criticalObjectParams, user.user)
loading.setLoading(false)
}
return (!editCriticalObjects ? null :
<PageWrapper title={`Edit Critical Object: ${criticalObjectsId}`}>
<div className='Main Card EditCriticalObjectFormWrapper'>
{configs.map((config, k)=> {
const Field = config.field
return (
<React.Fragment key={k}>
<Field
style={{ marginBottom: '15px'}}
name={config.name}
placeholder={config.name}
value={config.value}
initialValue={config.value}
initialValues={config.value}
uniqueIdentifier={k}
label={config.label}
onChange={(e) => onChange(e, config)}
/>
</React.Fragment>
)
})}
<Button
className='Button Dark Main'
text='Submit'
onClick={onSubmitClick}
/>
</div>
</PageWrapper>
)
}
export default editCriticalObjects

How to make field validation?

How to make field validation?
I have an object with fields from which I generate a form, and when submitting, I need to check each field so that it is not empty, I do this, but it doesn’t work
My form:
const [volunteerData, setVolunteerData] = useState({
fullName: {
value: '',
type: "text",
placeholder: "Name",
label: "Name"
},
phone: {
value: '',
type: "text",
placeholder: "Phone number",
label: "Phone number",
mask: "+7(999) 999 99 99"
}
)}
Render form:
const onHandleRenderForm = () => {
return Object.keys(volunteerData).map((items, idx) => {
const control = volunteerData[items];
return (
<div key={idx} className="content-data-box">
<label>{control.label}</label>
<InputMask
type={control.type}
placeholder={control.placeholder}
mask={control.mask}
onChange={e => onHandleFormData(e, items)}
/>
</div>
)
})
};
onChange input:
const onHandleFormData = (e, items) => {
const before = {...volunteerData};
const after = {...before[items]}
after.value = e.target.value;
before[items] = after;
setVolunteerData(before);
};
onClick (submit button):
const onHandleErrorBoundary = () => {
Object.keys(volunteerData).map(items => {
const errorData = items.value === '';
console.log(errorData)
})
};
Change items.value === '' to volunteerData[items].value !== ""
const onHandleErrorBoundary = () => {
Object.keys(volunteerData).map(items => {
const errorData = volunteerData[items].value !== "";
return console.log(errorData);
});
};
you can check here codesandbox

How to Disable Row in Antd Table

so I worked on a project using react js with umi js and antd as additional dependencies,
I had a problem when I got the task to disable each row in the antd table,
I tried to read the documentation antd but got nothing,
is it possible that you can do that? or there is another possible way to doing that
Thank you for the help
here's my code :
/* eslint-disable */
import React, { useState, useEffect, useRef } from 'react';
import { Modal, Button, Select, message, Radio, Table, Alert } from 'antd';
import _ from 'lodash';
import axios from 'axios';
import cookies from 'js-cookie';
import {_getCurrentBusiness} from '../../../utils/utils_business';
import {formatMessage } from 'umi-plugin-locale';
function DeleteConfirm (props) {
const user_auth = cookies.getJSON('ckmsbp');
const business = _getCurrentBusiness();
const [radio, setRadio] = useState('all');
const [role, setRole] = useState(null);
const [chRole, setChrole] = useState(null); //changerole
const [btn, setBtn] = useState(false);
const isMounted = useRef(null);
const roleRef = useRef(null);
const spanAmount = {fontSize: '1rem', fontWeight: 500,marginLeft: '1rem'}
useEffect( () => {
isMounted.current = true;
return () => isMounted.current = false;
}, [])
useEffect( () => {
if(!_.isNil(props.roles)) {
const updateRole = _.filter(props.roles, r => !_.eq(r.id, props.role.id) );
setRole(updateRole); //tampil di select
}
}, [props.roles]);
const handleSubmit = async () => {
let accountMeta = {}
const body = {status: 'deleted'}
const params = { _id: props.role.id}
console.log('radio', radio);
if(_.eq(radio, 'all')){
if(_.isNil(chRole)) {
message.error('data can not empty')
props.chVisible(null); //close modal
}
_.forEach(props.account, async acc => {
let bus = [];
if( !_.isNil(acc.business) && _.isString(acc.business) ) bus = JSON.parse(acc.business);
const find = _.findIndex(bus, b => {
return _.eq(b._id, business._id) && _.eq(b.role_capability, props.role.id)
})
bus[find].role_capability = chRole;
acc.business = JSON.stringify(bus)
accountMeta = {
value : acc.business,
key : 'business',
account_id: acc._id
}
await axios.put(`${API}/account-meta`, accountMeta, { headers: { Authorization: user_auth.token}});
})
} else if( _.eq(radio, 'manual')){
console.log('asd');
} else if (_.eq(radio, 'delete')){
_.forEach(props.account, async acc => {
let bus = [];
if( !_.isNil(acc.business) && _.isString(acc.business) ) bus = JSON.parse(acc.business);
const find = _.findIndex(bus, b => _.eq(b._id, business._id) && _.eq(b.role_capability, props.role.id) )
if(_.gt(find, -1)){
acc.business = JSON.stringify([])
accountMeta = {
value : acc.business,
key : 'business',
account_id: acc._id
}
await axios.put(`${API}/account-meta`, accountMeta, { headers: { Authorization: user_auth.token}});
}
})
}
const deleteResult = await axios.put(`${API}/master`, body, { params, headers: { Authorization: user_auth.token}});
if(!_.isNil(deleteResult) && _.isObject(deleteResult.data)){
let no = 1;
let data = []
let updateRole = _.filter(props.roles, r => !_.eq(r.id, props.role.id));
_.map(updateRole, role => {
role.no = no;
data.push(role)
no++
});
props.data(data); //tampil di select
message.success('data updated!')
props.chVisible(null); //close modal
}
}
const onChange = (data) => {
const value = data.target.value
setRadio(value);
}
const roleChange = (data) => {
setChrole(data)
}
//props column diambil dari datasource
const columns = [
{
title : 'No',
dataIndex: 'no',
key : 'no',
},
{
title : 'Account\'s Name',
dataIndex: 'name',
key : 'name',
},
{
title : 'Change Role',
dataIndex: 'id',
key : 'action',
render : (text, data) => renderButton(text, data)
},
];
const handleClick = (e, data) => {
setBtn(!btn)
console.log('e', e);
console.log('data', data);
}
const rowClassName = (record, index) => {
console.log('record', record);
console.log('index',index);
}
const renderButton = () => {
let arrayAllow = [];
arrayAllow.push(
<Select
showSearch
key = '1'
size = "small"
placeholder = "select"
ref = {roleRef}
optionFilterProp = "children"
style = {{ width: 100 }}
onChange = {(e) => roleChange(e)} //handle change role
filterOption = {(input, option) => _.toLower(option.props.children).indexOf(_.toLower(input)) >= 0}
>
{
!_.isNil(role) && _.map(role, (newVal) => {
return (<Select.Option
key = {newVal.id}
title = {newVal.title}
value = {newVal.id}>{newVal.title}
</Select.Option>)
})
}
</Select>
)
arrayAllow.push( <Button
type = {!btn ? "danger" : "primary"}
key = '2'
icon = {!btn ? "close" : "redo"}
size = "small"
onClick = {(e) => handleClick(e, props.role.id)}
/> )
return arrayAllow
}
// R E N D E R I N G
return(
<div>
<Modal
title = {`${formatMessage({id: 'ROLE_MANAGEMENT.DELETE_CONFIRM_TITLE'})} ${props.role.title}`}
visible = {props.visible}
onOk = {() => handleSubmit()}
onCancel = {() => props.cancel(null) }
width = {800}
>
<p>{formatMessage({id : 'ROLE_MANAGEMENT.DELETE_CONFIRM_STATEMENT', title: props.role.title})}</p>
<div style={{marginBottom: '1rem'}}>
<Radio.Group onChange = {(e) => onChange(e)} value={radio}>
<Radio value="all" >Changed All of people </Radio>
<Radio value="manual">Changed people manually</Radio>
<Radio value="delete">Total delete </Radio>
</Radio.Group>
</div>
{ _.eq(radio, 'all') &&
<div>
<Select
showSearch
ref = {roleRef}
size = "large"
style = {{ width: 200 }}
placeholder = {formatMessage({id: 'ACCOUNT.PLCHOLDER_ROLE'})}
optionFilterProp = "children"
onChange = {(e) => roleChange(e)} //handle change role
filterOption = {(input, option) => _.toLower(option.props.children).indexOf(_.toLower(input)) >= 0}
>
{
!_.isNil(role) && _.map(role, (newVal) => {
return ( <Select.Option
key = {newVal.id}
title = {newVal.title}
value = {newVal.id}
>{newVal.title}
</Select.Option> )
})
}
</Select>
<span style={spanAmount}>{`Total amount of people which have role ${props.role.title} : ${_.size(props.account)}`}</span>
</div>
}
{ _.eq(radio, 'manual') && <Table
dataSource = {props.account}
rowClassName = {rowClassName}
columns = {columns}
pagination = {{ pageSize: 50 }}
scroll = {{ y: 250 }}
/>
}
{ _.eq(radio, 'delete') && <Alert
message = "Attention!"
description = {formatMessage({id: 'ROLE_MANAGEMENT.DELETE_CONFIRM_DELETE'})}
type = "warning"
showIcon
/>
}
</Modal>
</div>
)
}
export default DeleteConfirm;
*the picture that I intend to disable when clicked on the danger button
In Antd there is no simple way to disable a row, so you can do it as workaround like below
So basically when you click on close button you can have state whether its been enabled or disabled as a boolean value
so each record will have that key. so based on that you can add a className and style it as disabled.
Here is a sample code snippet
App.js
import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import { Table } from "antd";
import "./styles.css";
function App() {
const dataSource = [
{
key: "1",
name: "Mike",
age: 32,
address: "10 Downing Street",
enabled: true
},
{
key: "2",
name: "John",
age: 42,
address: "10 Downing Street",
enabled: false
}
];
const columns = [
{
title: "Name",
dataIndex: "name",
key: "name"
},
{
title: "Age",
dataIndex: "age",
key: "age"
},
{
title: "Address",
dataIndex: "address",
key: "address"
}
];
return (
<>
<Table
dataSource={dataSource}
columns={columns}
rowClassName={record => !record.enabled && "disabled-row"}
/>
;
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
style.css
.disabled-row {
background-color: #dcdcdc;
pointer-events: none;
}
I hope this way you will have better understanding of solving the problem
Working codesandbox

Resources