Ant Design Dynamic Data does not binds to Select - reactjs

I am using react for a school project. The dynamic data does not binds to Options from Ant Design, react js. The result is an empty option list. In actual the data comes from an external API. For testing purpose I assigned the data the state variable. The data comes in 2D array, so I am mapping through the data twice.
Result is:
import { useEffect, useState } from "react";
import { Select } from "antd";
const { Option } = Select;
const Complete = () => {
const [list, setPersons] = useState([
[
{
id: 1,
personName: "Owan",
},
{
id: 2,
personName: "More",
},
{
id: 3,
personName: "Jaila",
},
{
id: 4,
personName: "Eerov",
},
],
[
{
id: 5,
personName: "Rell",
},
{
id: 6,
personName: "Juko",
}
]
]);
useEffect(() => {
console.log(list);
}, []);
return (
<Select
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{list.map((l) => {
l.map((person) => {
console.log(person);
<Option value={person.id}>
{person.personName}
</Option>;
});
})}
</Select>
);
};
export default Complete;

You just needed to update small one using ES6 feature here the script to combine 2 dimensional array to single array
{[].concat(...list).map((l) => <Option value={l.id}>{l.personName}</Option>)}
Here the full script:
import { useEffect, useState } from "react";
import { Select } from "antd";
const { Option } = Select;
const Complete = () => {
const [list, setPersons] = useState([
[
{
id: 1,
personName: "Owan",
},
{
id: 2,
personName: "More",
},
{
id: 3,
personName: "Jaila",
},
{
id: 4,
personName: "Eerov",
},
],
[
{
id: 5,
personName: "Rell",
},
{
id: 6,
personName: "Juko",
}
]
]);
useEffect(() => {
console.log(list);
}, []);
return (
<Select
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{[].concat(...list).map((l) => <Option value={l.id}>{l.personName}</Option>)}
</Select>
);
};
export default Complete;
visit live example demo

Try with the following code:
import { useEffect, useState } from "react";
import { Select } from "antd";
const { Option } = Select;
const Complete = () => {
const [list, setPersons] = useState([
[
{
id: 1,
personName: "Owan"
},
{
id: 2,
personName: "More"
},
{
id: 3,
personName: "Jaila"
},
{
id: 4,
personName: "Eerov"
}
],
[
{
id: 5,
personName: "Rell"
},
{
id: 6,
personName: "Juko"
}
]
]);
useEffect(() => {
console.log(list);
}, [list]);
return (
<Select
showSearch
style={{ width: 200 }}
placeholder="Select a person"
optionFilterProp="children"
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{list.map((l) => (
<>
{l.map((person) => (
<Option value={person.id}>{person.personName}</Option>
))}
</>
))}
</Select>
);
};
export default Complete;

Related

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);
}
};

How to Convert Class components to functional components in React?

import React, { PureComponent, Fragment } from 'react';
class Practice extends PureComponent {
state = {
options: [
{
name: 'Select…',
value: null,
},
{
name: 'Rui',
value: 3000,
},
{
name: 'Catla',
value: 3000,
},
{
name: 'Carpio',
value: 3000,
},
{
name: 'Tilapia',
value: 1750,
},
{
name: 'Mrigel',
value: 3000,
},
{
name: 'Pabda',
value: 3500,
},
{
name: 'Koi',
value: 750,
},
],
value: '?',
};
handleChange = (e) => {
this.setState({ value: e.target.value });
};
render() {
const { options, value } = this.state;
return (
<Fragment>
<select onChange={this.handleChange} value={value}>
{options.map(item => (
<option key={item.value} value={item.value}>
{item.name}
</option>
))}
</select>
<p>Oxygen Demand: {value}</p>
</Fragment>
);
}
}
export default Practice;
Use useState to handle state of options and value
Use useCallback to handle change events on select field
Return your rendered JSX
import React, { useCallback, useState } from "react";
function Practice() {
const [options, setOptions] = useState([
{
name: "Select…",
value: null,
},
{
name: "Rui",
value: 3000,
},
{
name: "Catla",
value: 3000,
},
{
name: "Carpio",
value: 3000,
},
{
name: "Tilapia",
value: 1750,
},
{
name: "Mrigel",
value: 3000,
},
{
name: "Pabda",
value: 3500,
},
{
name: "Koi",
value: 750,
},
]);
const [value, setValue] = useState("?");
const handleChange = useCallback((e) => {
setValue(e.target.value);
}, []);
return (
<>
<select onChange={handleChange} value={value}>
{options.map((item) => (
<option key={item.value} value={item.value}>
{item.name}
</option>
))}
</select>
<p>Oxygen Demand: {value}</p>
</>
);
}
export default Practice;
Convert like this:
import React, { useState, PureComponent, Fragment } from 'react';
let Practice = (praps) =>
let [options,soptions] = useState([
{
name: 'Select…',
value: null,
},
{
name: 'Rui',
value: 3000,
},
{
name: 'Catla',
value: 3000,
},
{
name: 'Carpio',
value: 3000,
},
{
name: 'Tilapia',
value: 1750,
},
{
name: 'Mrigel',
value: 3000,
},
{
name: 'Pabda',
value: 3500,
},
{
name: 'Koi',
value: 750,
},
]);
let [value,svalue]=useState('?')
let handleChange = (e) => {
svalue(e.target.value);
};
render() {
return (
<Fragment>
<select onChange={this.handleChange} value={value}>
{options.map(item => (
<option key={item.value} value={item.value}>
{item.name}
</option>
))}
</select>
<p>Oxygen Demand: {value}</p>
</Fragment>
);
} }
export default Practice;

How to implement AddAdiditions in React Sematic UI using Hooks?

I want to have a drop down in my application which allows the user to add an item to the dropdown. I am using React Sematic UI.
Sematic UI Dropdown ALlowAdditions
I am new to react hooks and I want to know how I can implement the onChange and onAddition function using hooks.
import React, { Component } from 'react'
import { Dropdown } from 'semantic-ui-react'
const options = [
{ key: 'English', text: 'English', value: 'English' },
{ key: 'French', text: 'French', value: 'French' },
{ key: 'Spanish', text: 'Spanish', value: 'Spanish' },
{ key: 'German', text: 'German', value: 'German' },
{ key: 'Chinese', text: 'Chinese', value: 'Chinese' },
]
class DropdownExampleAllowAdditions extends Component {
state = { options }
handleAddition = (e, { value }) => {
this.setState((prevState) => ({
options: [{ text: value, value }, ...prevState.options],
}))
}
handleChange = (e, { value }) => this.setState({ currentValue: value })
render() {
const { currentValue } = this.state
return (
<Dropdown
options={this.state.options}
placeholder='Choose Language'
search
selection
fluid
allowAdditions
value={currentValue}
onAddItem={this.handleAddition}
onChange={this.handleChange}
/>
)
}
}
export default DropdownExampleAllowAdditions
Any help would be greatly appreciated. Thanks in advance :)
import React, { useState } from "react";
import { Dropdown } from "semantic-ui-react";
const options = [
{ key: "English", text: "English", value: "English" },
{ key: "French", text: "French", value: "French" },
{ key: "Spanish", text: "Spanish", value: "Spanish" },
{ key: "German", text: "German", value: "German" },
{ key: "Chinese", text: "Chinese", value: "Chinese" }
];
const DropDownWithHooks = () => {
const [dropDownOptions, setDropDownOptions] = useState(options);
const [currentValue, setCurrentValue] = useState("");
const handleAddition = (e, { value }) => {
setDropDownOptions((prevOptions) => [
{ text: value, value },
...prevOptions
]);
};
const handleChange = (e, { value }) => setCurrentValue(value);
return (
<Dropdown
options={dropDownOptions}
placeholder="Choose Language"
search
selection
fluid
allowAdditions
value={currentValue}
onAddItem={handleAddition}
onChange={handleChange}
/>
);
};
export default DropDownWithHooks;
Working Sandbox

Filter/update already rendered chart.js in react.js

I'm new here, because I have decided to dive into programming, so I can fill free time between treatments in the hospital. I'm absolutely new in the programming field with no previous coding background.
The summary:
I am working on a simple page, where I fetch data from a Postgre database that is visualized using chart.js. The page is a built-in cube.js playground, using a Reactjs template. Currently, I can display various charts depending on my criteria. Like display monthly sales of a certain product in Australia. Or, I can display a second chart with daily sales in the countries I choose. Or ignore all sales that were in a certain currency. Right now, every new criterion means I have to use cube.js playground and generate a new chart on the page.
What I would like to achieve is to be able to filter already rendered charts (by a dropdown button outside the chart or inside the chart, it doesn't matter too much) and having the chart updated. Something like the pictures here, where the OP can filter charts based on the date, factory, etc.
I've tried Chart.js Example with Dynamic Dataset, chart.js tutorial on
Updating Charts and various others. But I can't seem to be able to implement any of those solutions in my code.
Here is my current code:
ChartRenderer.js
import React from "react";
import PropTypes from "prop-types";
import { useCubeQuery } from "#cubejs-client/react";
import Row from "react-bootstrap/Row";
import Spin from "react-bootstrap/Spinner";
import Col from "react-bootstrap/Col";
import { Statistic, Table } from "antd";
import { Line, Bar, Pie } from "react-chartjs-2";
const COLORS_SERIES = [
"#931F1D",
"#141446",
"#7A77FF",
];
const commonOptions = {
maintainAspectRatio: true,
};
const TypeToChartComponent = {
line: ({ resultSet }) => {
const data = {
labels: resultSet.categories().map((c) => c.category),
datasets: resultSet.series().map((s, index) => ({
label: s.title,
data: s.series.map((r) => r.value),
borderColor: COLORS_SERIES[index],
backgroundColor: COLORS_SERIES[index],
fill: false,
tension: 0.4,
})),
};
const options = { ...commonOptions };
return <Line data={data} options={options} />;
},
bar: ({ resultSet }) => {
const data = {
labels: resultSet.categories().map((c) => c.category),
datasets: resultSet.series().map((s, index) => ({
label: s.title,
data: s.series.map((r) => r.value),
backgroundColor: COLORS_SERIES[index],
fill: false,
})),
};
const options = {
...commonOptions,
scales: {
xAxes: [
{
stacked: true,
},
],
},
};
return <Bar data={data} options={options} />;
},
area: ({ resultSet }) => {
const data = {
labels: resultSet.categories().map((c) => c.category),
datasets: resultSet.series().map((s, index) => ({
label: s.title,
data: s.series.map((r) => r.value),
backgroundColor: COLORS_SERIES[index],
fill: true,
})),
};
const options = {
...commonOptions,
scales: {
yAxes: [
{
stacked: true,
},
],
},
};
return <Line data={data} options={options} />;
},
pie: ({ resultSet }) => {
const data = {
labels: resultSet.categories().map((c) => c.category),
datasets: resultSet.series().map((s) => ({
label: s.title,
data: s.series.map((r) => r.value),
backgroundColor: COLORS_SERIES,
hoverBackgroundColor: COLORS_SERIES,
borderColor: COLORS_SERIES,
hoverBorderColor: "white",
hoverOffset: 10,
})),
};
const options = { ...commonOptions };
return <Pie data={data} options={options} />;
},
number: ({ resultSet }) => {
return (
<Row
type="flex"
justify="space-around"
align="middle"
style={{ height: "100%" }}
>
<Col align="left">
{resultSet.seriesNames().map((s) => (
<Statistic value={resultSet.totalRow()[s.key]} />
))}
</Col>
</Row>
);
},
table: ({ resultSet, pivotConfig }) => {
return (
<Table
pagination={false}
columns={resultSet.tableColumns(pivotConfig)}
dataSource={resultSet.tablePivot(pivotConfig)}
/>
);
},
};
const TypeToMemoChartComponent = Object.keys(TypeToChartComponent)
.map((key) => ({
[key]: React.memo(TypeToChartComponent[key]),
}))
.reduce((a, b) => ({ ...a, ...b }));
const renderChart =
(Component) =>
({ resultSet, error }) =>
(resultSet && <Component resultSet={resultSet} />) ||
(error && error.toString()) || <Spin animation="grow text-primary" />;
const ChartRenderer = ({ vizState }) => {
const { query, chartType } = vizState;
const component = TypeToMemoChartComponent[chartType];
const renderProps = useCubeQuery(query);
return component && renderChart(component)(renderProps);
};
ChartRenderer.propTypes = {
vizState: PropTypes.object,
cubejsApi: PropTypes.object,
};
ChartRenderer.defaultProps = {
vizState: {},
cubejsApi: null,
};
export default ChartRenderer;
DashBoardPage.js
import React from "react";
import Col from "react-bootstrap/Col";
import DateRangePicker from 'react-bootstrap-daterangepicker';
import ChartRenderer from "../components/ChartRenderer";
import Dashboard from "../components/Dashboard";
import DashboardItem from "../components/DashboardItem";
const DashboardItems = [
{
id: 0,
name: "Sold by customers today",
vizState: {
query: {
measures: ["PostgreSqlTable.amount"],
timeDimensions: [
{
dimension: "PostgreSqlTable.added",
granularity: "day",
dateRange: "Today",
},
],
order: {},
dimensions: [],
filters: [
{
member: "PostgreSqlTable.operation",
operator: "contains",
values: ["Sell"],
},
],
},
chartType: "number",
},
},
{
id: 1,
name: "Bought by customers today",
vizState: {
query: {
measures: ["PostgreSqlTable.amount"],
timeDimensions: [
{
dimension: "PostgreSqlTable.added",
dateRange: "Today",
},
],
order: {},
filters: [
{
member: "PostgreSqlTable.operation",
operator: "contains",
values: ["Buy"],
},
],
},
chartType: "number",
},
},
{
id: 2,
name: "Money in the wallet",
vizState: {
query: {
measures: ["PostgreSqlTable.amount"],
timeDimensions: [
{
dimension: "PostgreSqlTable.added",
},
],
order: {
"PostgreSqlTable.amount": "desc",
},
dimensions: ["PostgreSqlTable.currency"],
filters: [
{
member: "PostgreSqlTable.currency",
operator: "equals",
values: ["EUR"],
},
],
},
chartType: "number",
},
},
{
id: 3,
name: "Monthly sales filtered by week",
vizState: {
query: {
measures: ["PostgreSqlTable.amount"],
timeDimensions: [
{
dimension: "PostgreSqlTable.added",
granularity: "week",
dateRange: "This month",
},
],
order: {
"PostgreSqlTable.amount": "desc",
},
dimensions: ["PostgreSqlTable.operation"],
filters: [
{
member: "PostgreSqlTable.operation",
operator: "notContains",
values: ["Register"],
},
],
limit: 5000,
},
chartType: "line",
},
},
{
id: 4,
name: "Countries with most customers",
vizState: {
query: {
measures: ["PostgreSqlTable.count"],
timeDimensions: [
{
dimension: "PostgreSqlTable.added",
},
],
order: {
"PostgreSqlTable.count": "desc",
},
dimensions: ["PostgreSqlTable.country"],
limit: 5,
},
chartType: "pie",
},
},
];
const DashboardPage = () => {
const dashboardItem = (item) => (
<Col className="col-4">
<DashboardItem title={item.name}>
<ChartRenderer vizState={item.vizState} />
</DashboardItem>
</Col>
);
const Empty = () => (
<div
style={{
textAlign: "center",
padding: 12,
}}
>
<h2>
No items added
</h2>
</div>
);
return DashboardItems.length ? (
<Dashboard dashboardItems={DashboardItems}>
{DashboardItems.map(dashboardItem)}
</Dashboard>
) : (
<Empty />
);
};
export default DashboardPage;
At this moment, I have no clue how to implement the filter in react.js+chart.js. I have also tried to update the array, but no success (I followed also this tutorial)
I would be most grateful for any help.
Thank you in advance, stay healthy.
Tatsu
I'd recommend using the <QueryBuilder/> component available in the Cube.js-React integration; this component provides a similar interface as that in the Developer Playground.

How can I handle different types of values for a select component?

I am new to React, I am trying to do a select component, BUT the initial value coming from the API as a string so the selected value always empty because the values should be INT, and I can't change the labels to string since updating the gender should send an Int. any help what should I do here ?
const [gender, setGender] = useState(user.gender)
const genderOptions = [
{ id: 0, value: 0, label: 'Prefer Not To Answer' },
{ id: 1, value: 1, label: 'Female' },
{ id: 2, value: 2, label: 'Male' },
]
const handleChange = () => {
setGender(parseInt(event.target.value,10))
}
return (
<FormControl variant="outlined">
<Styledelect
id="genderId"
name="gender"
displayEmpty
value={gender}
onChange={handleChange}
>
{genderOptions.map((data) => (
<StyledMenuItem key={data.id} value={data.value}>
{data.label}
</StyledMenuItem>
))}
</Styledelect>
</FormControl>
)
mutation updateEventWorker($eventWorkerId: ID!,$gender: Int) {
updateEventWorker(eventWorkerId: $eventWorkerId, gender: $gender) {
eventWorker {
id
user {
gender
}
}
}
}
query eventWorkers {
eventWorkers {
user {
gender
}
}
}
RESULT:
{ "data": {
"eventWorkers": [{
"user": {
"gender": "female"
}
}]
}}
You could first look for the value then use it as initial state:
const genderOptions = [
{ id: 0, value: 0, label: 'Prefer Not To Answer' },
{ id: 1, value: 1, label: 'Female' },
{ id: 2, value: 2, label: 'Male' },
];
const initalState = genderOptions.find(opt => opt.label.toLowerCase() === user.gender.toLowerCase())?.value || null;
...
const [gender, setGender] = useState(initalState);

Resources