Using props in functional component - reactjs

I am getting array in props which is props.logsInfo.logs and I want to use it according to the number of elements in array instead of hard coding it like props.logsInfo.logs[0]['id']. I want to use map.Logs array size can be more than one.I don't want to write one more cells: [
{ key: 'cell-0', children: props.logsInfo.logs[1]['id'] },How can i achieve it??
import React from 'react';
import Table from 'terra-table';
const StripedTable = props => (
<Table
summaryId="striped-table"
summary="This table displays striped rows."
numberOfColumns={4}
dividerStyle="horizontal"
headerData={{
cells: [
{ id: 'header-Id', key: 'id', children: 'Id' },
{ id: 'header-vendorId', key: 'vendorId', children: 'VendorId' },
{ id: 'header-userId', key: 'userId', children: 'UserId' },
{ id: 'header-payLoad', key: 'payLoad', children: 'PayLoad' },
],
}}
bodyData={[
{
rows: [
{
key: 'row-0',
cells: [
{ key: 'cell-0', children: props.logsInfo.logs[0]['id'] },
{ key: 'cell-1', children: props.logsInfo.logs[0]['vendorId'] },
{ key: 'cell-2', children: props.logsInfo.logs[0]['userId'] },
{ key: 'cell-3', children: props.logsInfo.logs[0]['payLoad']},
],
},
],
},
]}
/>
);
export default StripedTable;

Yes, you can use .map:
bodyData={[
{
rows: props.logsInfo.logs.map(log => ({
key: log.id,
cells: [
{ key: 'cell-0', children: log.id },
{ key: 'cell-1', children: log.vendorId },
{ key: 'cell-2', children: log.userId },
{ key: 'cell-3', children: log.payLoad},
],
}),
},
]}
You can also do the same for cells if you keep an array with the field names around:
const fields = ['id', 'vendorId', 'userId', 'payLoad'];
// ...
bodyData={[
{
rows: props.logsInfo.logs.map(log => ({
key: log.id,
cells: fields.map(field => ({key: field, children: log[field]})),
}),
},
]}

Related

Antd Cascader component value/defaultValue showing ID instead of label

So I am using the Antd Cascader component (for the first time, having used Antd Select for most other things for the past few months). However, it isn't quite working yet. I have the options basically like this (but with a lot more options, only 3 levels deep tho like this):
const options = [
{
label: 'Base 1',
value: 'base_1',
children: [
{
label: 'Middle a',
value: 'middle_a',
children: [
{
label: 'Foo',
value: 'd57b2b75-4afa-4a16-8991-fc736bce8cd5',
},
{
label: 'Bar',
value: 'd12b2b75-4afa-4a16-8991-fc736bce8cec',
}
]
},
{
label: 'Middle b',
value: 'middle_b',
children: [
{
label: 'Baz',
value: 'd32b2b75-4afa-4a16-8991-fc736bce8cdd',
},
{
label: 'Quux',
value: 'dabb2b75-4afa-4a16-8991-fc736bce8ced',
}
]
}
]
},
{
label: 'Base 2',
value: 'base_2',
children: [
{
label: 'Middle a',
value: 'middle_a',
children: [
{
label: 'Helo',
value: 'd32bce75-4afa-4a16-8991-fc736bce8cdd',
},
{
label: 'World',
value: 'dabbac75-4afa-4a16-8991-fc736bce8ced',
}
]
}
]
}
]
I configure the component like this:
<Cascader
options={options}
getPopupContainer={trigger => trigger.parentNode}
multiple={multiple}
displayRender={label => {
return label.join(' / ');
}}
value={defaultValue}
// eslint-disable-next-line #typescript-eslint/no-explicit-any
onChange={(val: any, options: any) => {
if (multiple) {
const ids = serializeCascaderOptionValues(options);
onChange?.(ids, options);
} else {
onChange?.(val[2] ? String(val[2]) : undefined, options);
}
}}
showSearch={{
filter: (input: string, path) => {
return path.some(
option =>
String(option?.label).toLowerCase().indexOf(input.toLowerCase()) >
-1
);
},
}}
/>
Where, here, value or defaultValue I am passing in an array like ['d32bce75-4afa-4a16-8991-fc736bce8cdd'], which maps to Base 2 / Middle a / Helo. When I select the value Base 2 / Middle a / Helo from the UI, it shows correctly in the input like that. But when I save it and refresh the page (persisting to the backend, and pass in value={value} like value={['d32bce75-4afa-4a16-8991-fc736bce8cdd']}, it shows the ID hash in the input instead of the nice string Base 2 / Middle a / Helo. When I log displayRender={label...}, the label is showing the [ID-hash], rather than an array of like ['Base 2', 'Middle a', 'Helo']. What am I doing wrong, how do I get it to show properly?

Antd Tree component, how to add cache data

I have a problem with the Tree component of the Antd library. The problem is presented on the video. Namely that the component after changing the data tree renders anew and after selecting an option the previous ones are cleared. Does anyone have any idea how to solve this, so that after changing the data tree, the previous options that were selected are still selected?
import React, { useState } from 'react';
import { Tree } from 'antd';
import { Wrapper, TreeContainer } from './Tree.styled';
const treeData = [
{
title: '0-1',
key: '0-1',
children: [
{ title: '0-1-0-0', key: '0-0-0-0', },
{ title: '0-1-0-1', key: '0-0-0-1' },
{ title: '0-1-0-2', key: '0-0-0-2' },
],
},
{
title: '0-2',
key: '0-2',
},
{
title: '0-3',
key: '0-3',
children: [
{ title: '0-2-0-0', key: '0-2-0-0', },
{ title: '0-2-0-1', key: '0-2-0-1' },
{ title: '0-2-0-2', key: '0-2-0-2' },
],
},
{
title: '0-4',
key: '0-4',
children: [
{ title: '0-3-0-0', key: '0-3-0-0', },
{ title: '0-3-0-1', key: '0-3-0-1' },
{ title: '0-3-0-2', key: '0-3-0-2' },
],
},
{
title: '0-5',
key: '0-5',
children: [
{ title: '0-4-0-0', key: '0-4-0-0', },
{ title: '0-4-0-1', key: '0-4-0-1' },
{ title: '0-4-0-2', key: '0-4-0-2' },
],
},
];
const AntdTree = () => {
const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]);
const [optionValue, setOptionValue] = useState<any>();
const tree = treeData.filter(filterValue => filterValue.key == (!!optionValue ? optionValue : filterValue.key)).map(data => data)
const onCheck = (checkedKeysValue: any) => {
console.log('onCheck', checkedKeysValue);
setCheckedKeys(checkedKeysValue);
};
return (
<>
<Wrapper>
<TreeContainer>
<select value={optionValue} onChange={e => setOptionValue(e.target.value)} >
<option value={'0-1'}>0-1</option>
<option value={'0-2'}>0-2</option>
<option value={'0-3'}>0-3</option>
<option value={'0-4'}>0-4</option>
<option value={'0-5'}>0-5</option>
</select>
<button onClick={() => setOptionValue('')} >Delete</button>
<Tree
checkable
onCheck={onCheck}
checkedKeys={checkedKeys}
treeData={tree}
/>
</TreeContainer>
</Wrapper>
</>
);
};
export default AntdTree;
Link to video with problem: https://youtu.be/BLEzQck3cZo
Thanks for your help !😊
onCheck callback in your case rewrite new values. You can save previous values using prevState in useState hook like so:
const onCheck = (checkedKeysValue: React.Key[], info: any) => {
console.log('onCheck', checkedKeysValue);
console.log('info', info);
if (info.checked) { // handle check case
setCheckedKeys(prevState => [...prevState, ...checkedKeysValue]);
} else { // handle uncheck case
setCheckedKeys(checkedKeysValue);
}
};

Type has no properties in common with type 'ColumnType<any>'

I am writing an app with react and ant design
I want to use antd table
but it does not show my data
Code
const ListOfProperties = () => {
const columns = [
{
type: "Type",
state: "State",
location: "Location",
},
];
const properties = [
{
type: "Flat",
state: "Anambra",
location: "Udoka",
},
{
type: "Flat",
state: "Anambra",
location: "Udoka",
},
];
return (
<Skeleton active loading={loading}>
<Table columns={columns} dataSource={properties} />
</Skeleton>
);
};
export default ListOfProperties;
I created an array of objects which I passed to the data source and columns to the columns
as stated in the docs
but I am getting error
Error
Type '{ type: string; state: string; location: string; }' has no properties in common with type 'ColumnType<any>'.
you need to provide title, dataIndex and key. Always look it up in the documentation first.
const columns = [
{
title: "Type",
dataIndex: "type",
key: "type"
},
{
title: "State",
dataIndex: "state",
key: "state"
},
{
title: "Location",
dataIndex: "location",
key: "location"
},
];

I want to create checkbox checked in nested data in react js

My data is in nested array objects. I want to make checked/unchecked the nodes like a tree view. ie. when any child node is selected then the parent node is checked itself.
This is my nested JSON. From this object, I create a tree view from this data:
const nodes = [
{
value: "/app",
label: "app",
children: [
{
value: "/app/Http",
label: "Http",
children: [
{
value: "/app/Http/Controllers",
label: "Controllers",
children: [
{
value: "/app/Http/Controllers/WelcomeController.js",
label: "WelcomeController.js",
},
],
},
{
value: "/app/Http/routes.js",
label: "routes.js",
},
],
},
{
value: "/app/Providers",
label: "Providers",
children: [
{
value: "/app/Http/Providers/EventServiceProvider.js",
label: "EventServiceProvider.js",
},
],
},
],
},
{
value: "/config",
label: "config",
children: [
{
value: "/config/app.js",
label: "app.js",
},
{
value: "/config/database.js",
label: "database.js",
},
],
},
{
value: "/public",
label: "public",
children: [
{
value: "/public/assets/",
label: "assets",
children: [
{
value: "/public/assets/style.css",
label: "style.css",
},
],
},
{
value: "/public/index.html",
label: "index.html",
},
],
},
{
value: "/.env",
label: ".env",
},
{
value: "/.gitignore",
label: ".gitignore",
},
{
value: "/README.md",
label: "README.md",
},
];
I am using this function to make parent checked when child is checked.
checkChange(targetNode: any, event) {
/// debugger;
const targetNodeId = targetNode.id;
this.findIndexNestedforCheckbox(targetNode, targetNodeId);
let newTableData = [...this.state.tableData];
this.setState({ tableData: newTableData, isActionFooter: true });
}
findIndexNestedforCheckbox(data, index) {
if (data.id === index) data.isChecked = "Yes";
let result;
const i = (data.children || []).findIndex((child) => {
child.isChecked = "Yes";
return (result = this.findIndexNestedforCheckbox(child, index));
});
if (result) return [i, ...result];
}
npm install react-checkbox-tree
import React from 'react';
import CheckboxTree from 'react-checkbox-tree';
const nodes = [{
value: 'mars',
label: 'Mars',
children: [
{ value: 'phobos', label: 'Phobos' },
{ value: 'deimos', label: 'Deimos' },
],
}];
class Widget extends React.Component {
state = {
checked: [],
expanded: [],
};
render() {
return (
<CheckboxTree
nodes={nodes}
checked={this.state.checked}
expanded={this.state.expanded}
onCheck={checked => this.setState({ checked })}
onExpand={expanded => this.setState({ expanded })}
/>
);
}
}

Filter Array based on a property in the array of its objects

Given is following data structure
const list = [
{
title: 'Section One',
data: [
{
title: 'Ay',
},
{
title: 'Bx',
},
{
title: 'By',
},
{
title: 'Cx',
},
],
},
{
title: 'Section Two',
data: [
{
title: 'Ay',
},
{
title: 'Bx',
},
{
title: 'By',
},
{
title: 'Cx',
},
],
},
];
What i want to do ist to filter this list based on title property in the data array of each object.
An example would be to have the list where the title property of the childs starts with "B", so the list will look like that:
const filteredList = [
{
title: 'Section One',
data: [
{
title: 'Bx',
},
{
title: 'By',
}
],
},
{
title: 'Section Two',
data: [
{
title: 'Bx',
},
{
title: 'By',
}
],
},
];
What i tried so far was something like that:
const items = list.filter(item =>
item.data.find(x => x.title.startsWith('A')),
);
or
const filtered = list.filter(childList => {
childList.data.filter(item => {
if (item.title.startsWith('B')) {
return item;
}
return childList;
});
});
But i think i am missing a major point here, maybe some of you could give me a tip or hint what i am doing wrong
Best regards
Your issue is that you're doing .filter() on list. This will either keep or remove your objects in list. However, in your case, you want to keep all objects in list and instead map them to a new object. To do this you can use .map(). This way you can map your objects in your list array to new objects which contain filtered data arrays. Here's an example of how you might do it:
const list=[{title:"Section One",data:[{title:"Ay"},{title:"Bx"},{title:"By"},{title:"Cx"}]},{title:"Section Two",data:[{title:"Ay"},{title:"Bx"},{title:"By"},{title:"Cx"}]}];
const filterByTitle = (search, arr) =>
arr.map(
({data, ...rest}) => ({
...rest,
data: data.filter(({title}) => title.startsWith(search))
})
);
console.log(filterByTitle('B', list));

Resources