Changing object in array using useState - reactjs

I'd like to change each Data[0].datasets label using the array in Axisstate
I tried to put Axis's label to each Data label but i doesn't work, and it's not what i expected it would be.
both are changed to as same as the last one that i write.
and I'm trying to add more elements to datasets using the AxisHandler function to use push.
and It's doesn't change as soon as i click AxisUpdatefunction.
I'd like to know why it happens and what i should do .
Thank you in advance.
my code is like this:
import React, { useState } from "react";
import { Data, AppendData } from "./Data";
const Changeable = () => {
const [Axis, setAxis] = useState([]);
const changeHandler = index => e => {
setAxis(Axis =>
Axis.map((el, i) => (i === index ? { ...el, label: e.target.value } : el))
);
};
const AxisHandler = e => {
setAxis([
...Axis,
{
label: "",
data: "",
backgroundColor: "",
},
]);
Data[0].datasets.push(AppendData);
};
const AxisUpdate = () => {
if (Data[0].datasets[1].label) {
Data[0].datasets[1].label = Axis[0].label;
}
if (Data[0].datasets[2].label) {
Data[0].datasets[2].label = Axis[1].label;
}
};
return (
<div>
<button onClick={AxisHandler}>addAxis</button>
<>
{Axis.map((data, index) => (
<>
<input
placeholder={index + 1}
type="text"
onChange={changeHandler(index)}
/>
</>
))}
</>
<button onClick={AxisUpdate}>changeLabel</button>
<br />
<h1>{Data[0].datasets[0].label}</h1>
<br />
<h1>{Data[0].datasets[1] && Data[0].datasets[1].label}</h1>
<br />
<h1>{Data[0].datasets[2] && Data[0].datasets[2].label}</h1>
</div>
);
};
export default Changeable;
Data and AppendData
export const defaultLabels = [
"0",
"0",
"0",
"0",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
];
export const defaultDatas = [
13000, 11000, 9000, 4000, 14000, 16000, 20000, 11000, 14000, 11200, 12000,
12000,
];
export const defaultBackgroundColor = [
"#ff6385e1",
"#36a3ebf0",
"#ffcf56c8",
"#4bc0c0be",
"#9966ffa2",
"#ffa040b2",
];
export let AppendData = {
label: "dataSetting",
data: defaultDatas,
backgroundColor: defaultBackgroundColor,
};
export let Data = [
{
labels: defaultLabels,
datasets: [
{
label: "First",
data: defaultDatas,
backgroundColor: defaultBackgroundColor,
},
],
}, ///1번
{
labels: defaultLabels,
datasets: [
{
label: "Second",
data: defaultDatas,
backgroundColor: defaultBackgroundColor,
},
],
},
{
labels: defaultLabels,
datasets: [
{
label: "Third",
data: defaultDatas,
backgroundColor: defaultBackgroundColor,
},
],
},
]; ///2번

Related

How can i use react-drag-listview with functional components to make draggable columns with antd-table?

I'm trying to create a draggable table with antd, but i always use functionalcomponents in react and all the examples and doc that i found in internet is using class components and that=this stufs like. I don't know how can i use react-drag-listview library with the functional components.
this.state = {
columns: [
{
title: <span className="dragHandler">Key</span>,
dataIndex: "key",
render: (text) => <span>{text}</span>,
width: 50
},
{
title: <span className="dragHandler">Name</span>,
dataIndex: "name",
width: 200
},
{
title: <span className="dragHandler">Gender</span>,
dataIndex: "gender",
width: 100
},
{
title: <span className="dragHandler">Age</span>,
dataIndex: "age",
width: 100
},
{
title: <span className="dragHandler">Address</span>,
dataIndex: "address"
}
]
};
const that = this;
this.dragProps = {
onDragEnd(fromIndex, toIndex) {
const columns = [...that.state.columns];
const item = columns.splice(fromIndex, 1)[0];
columns.splice(toIndex, 0, item);
that.setState({
columns
});
},
nodeSelector: "th",
handleSelector: ".dragHandler",
ignoreSelector: "react-resizable-handle"
};
}
This a small piece of code that I'm trying to copy from, but i don't understand it.
Even an exaple of any small code where i can see how to use with functional components it may work for me.
Tis is the url of the example above: https://codesandbox.io/s/table-column-sortable-resizable-st9bt?file=/index.js
React Drag List View Using Functional Component
import "./index.css";
import { useState } from "react";
import { Resizable } from "react-resizable";
import { Table } from "antd";
import ReactDragListView from "react-drag-listview";
const ResizableTitle = (props) => {
const { onResize, width, ...restProps } = props;
if (!width) {
return <th {...restProps} />;
}
return (
<Resizable
width={width}
height={0}
handle={
<span
className='react-resizable-handle'
onClick={(e) => {
e.stopPropagation();
}}
/>
}
onResize={onResize}
draggableOpts={{ enableUserSelectHack: false }}
>
<th {...restProps} />
</Resizable>
);
};
const data = [
{ key: "1", name: "Boran", gender: "male", age: "12", address: "New York" },
{ key: "2", name: "JayChou", gender: "male", age: "38", address: "TaiWan" },
{ key: "3", name: "Lee", gender: "female", age: "22", address: "BeiJing" },
{ key: "4", name: "ChouTan", gender: "male", age: "31", address: "HangZhou" },
{ key: "5", name: "AiTing", gender: "female", age: "22", address: "Xi’An" },
];
const components = { header: { cell: ResizableTitle } };
const App = () => {
const [columns, setColumns] = useState([
{
title: <span className='dragHandler'>Key</span>,
dataIndex: "key",
render: (text) => <span>{text}</span>,
width: 50,
},
{
title: <span className='dragHandler'>Name</span>,
dataIndex: "name",
width: 200,
},
{
title: <span className='dragHandler'>Gender</span>,
dataIndex: "gender",
width: 100,
},
{
title: <span className='dragHandler'>Age</span>,
dataIndex: "age",
width: 100,
},
{
title: <span className='dragHandler'>Address</span>,
dataIndex: "address",
},
]);
const onDragEnd = (fromIndex, toIndex) => {
setColumns((prev) => {
const nextColumns = [...prev];
const item = nextColumns.splice(fromIndex, 1)[0];
nextColumns.splice(toIndex, 0, item);
return nextColumns;
});
};
const handleResize = (size, index) => {
setColumns((prev) => {
const nextColumns = [...prev];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
return nextColumns;
});
};
const tableColumns = columns.map((col, index) => ({
...col,
onHeaderCell: (column) => ({
width: column.width,
onResize: (e, { size }) => handleResize(size, index),
}),
}));
return (
<ReactDragListView.DragColumn
onDragEnd={onDragEnd}
nodeSelector='th'
handleSelector='.dragHandler'
ignoreSelector='react-resizable-handle'
>
<Table bordered columns={tableColumns} dataSource={data} components={components} />
</ReactDragListView.DragColumn>
);
};
export default App;

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.

React Native Redux Shopping Cart App Problems

I am trying to make an application that allows the user to select 'Add to cart' within my DetailsComponent.js page. I am currently updating an array within my store named 'cart' with ids that correspond to products within a products array within the store. I have checked the debugger and the product id is correctly being added to the cart array.
I am using the following code to show products on my cart page that match the product ids in my cart but my cart is currently showing nothing.
CartComponent.js
import React, { Component } from 'react';
import { FlatList, View, Text, Alert } from 'react-native';
import { ListItem } from 'react-native-elements';
import { connect } from 'react-redux';
import { baseUrl } from '../shared/baseUrl';
import { Loading } from './LoadingComponent';
import { removeCart } from '../redux/ActionCreators';
const mapStateToProps = state => {
return {
products: state.products,
cart: state.cart
}
}
const mapDispatchToProps = dispatch => ({
removeCart: (id) => dispatch(removeCart(id))
});
class CartScreen extends Component {
render() {
const renderMenuItem = ({item, index}) => {
return(
<ListItem
key={index}
bottomDivider
>
<ListItem.Content>
<ListItem.Title>
{item.name}
</ListItem.Title>
<ListItem.Subtitle>
{item.quantity} chargers: ${item.price}
</ListItem.Subtitle>
</ListItem.Content>
</ListItem>
);
}
if (this.props.cart.isLoading) {
return(
<Loading />
)
}
else if (this.props.cart.errMess) {
return(
<Text>{this.props.cart.errMess}</Text>
)
}
else {
return(
<View>
<Text>
Cart
</Text>
<FlatList
data={this.props.products.products.filter(product => this.props.cart.cart.some(el => el === product.id))}
renderItem={renderMenuItem}
keyExtractor={item => item.id.toString()}
/>
</View>
);
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(CartScreen);
I have included my other files for more information.
I have different DropDownPicker values that correspond to the product IDs in my redux store. These items in the store have quantity and price values to be used in the CartComponent.js.
DetailsComponent.js
import React, { Component } from 'react';
import { Text, View, Image, Button, FlatList, StyleSheet, ScrollView} from 'react-native';
import DropDownPicker from 'react-native-dropdown-picker';
import { baseUrl } from '../shared/baseUrl';
import { connect } from 'react-redux';
import { Loading } from './LoadingComponent';
import { postCart } from '../redux/ActionCreators';
const mapStateToProps = state => {
return{
chargers: state.chargers,
utensils: state.utensils,
orders: state.orders,
products: state.products
}
}
const mapDispatchToProps = dispatch => ({
postCart: (id) => dispatch(postCart(id))
})
class DetailsScreen extends Component {
constructor(props) {
super();
this.state = {
itemId: '',
orderAmount: '',
orderPrice: ''
}
}
addToCart(id) {
this.props.postCart(id);
}
render() {
const categoryName = this.props.route.params.categoryName;
const productId = this.props.route.params.menuId;
const item = this.props[categoryName][categoryName][productId];
if (categoryName === "chargers") {
if (productId === 0) {
var amounts = [
{label: '50', value: '1'},
{label: '100', value: '2'},
{label: '150', value: '3'},
{label: '200', value: '4'},
{label: '250', value: '5'},
{label: '300', value: '6'},
{label: '350', value: '7'},
{label: '400', value: '8'},
{label: '450', value: '9'},
{label: '500', value: '10'},
{label: '550', value: '11'},
{label: '600', value: '12'},
];
}
else if (productId === 1) {
var amounts = [
{label: '50', value: '14'},
{label: '100', value: '15'},
{label: '150', value: '16'},
{label: '200', value: '17'},
{label: '250', value: '18'},
{label: '300', value: '19'},
{label: '350', value: '20'},
{label: '400', value: '21'},
{label: '450', value: '22'},
{label: '500', value: '23'},
{label: '550', value: '24'},
{label: '600', value: '25'},
];
}
else if (productId === 2) {
var amounts = [
{label: '50', value: '27'},
{label: '100', value: '28'},
{label: '150', value: '29'},
{label: '200', value: '30'},
{label: '250', value: '31'},
{label: '300', value: '32'},
{label: '350', value: '33'},
{label: '400', value: '34'},
{label: '450', value: '35'},
{label: '500', value: '36'},
{label: '550', value: '37'},
{label: '600', value: '38'},
];
}
}
else if (categoryName === "utensils") {
if (productId === 0) {
var amounts = [
{label: '1', value: '40'},
{label: '2', value: '41'},
{label: '3', value: '42'},
{label: '4', value: '43'},
{label: '5', value: '44'},
];
}
else if (productId === 1) {
var amounts = [
{label: '1', value: '46'},
{label: '2', value: '47'},
{label: '3', value: '48'},
{label: '4', value: '49'},
{label: '5', value: '50'},
];
}
}
if (this.props[categoryName].isLoading) {
return(
<Loading />
)
}
else if (this.props[categoryName].errMess) {
return(
<Text>
{this.props[categoryName][categoryName].errMess}
</Text>
)
}
else {
return(
<ScrollView>
<Text style={styles.title}>
{item.name}
</Text>
<Text>
{item.category}
</Text>
<View style={{flex: 1, flexDirection: 'row'}}>
<Image
style={styles.image}
source={{uri: baseUrl + item.image}}
/>
<DropDownPicker
items={amounts}
defaultNull
placeholder="Select amount"
containerStyle={{height: 40, width: 100}}
itemStyle={{
justifyContent: 'flex-start'
}}
onChangeItem={item => this.setState({
itemId: this.props.products.products[item.value].id,
orderAmount: this.props.products.products[item.value].quantity,
orderPrice: this.props.products.products[item.value].price
})}
/>
</View>
<Text>
{item.description}
</Text>
<Text>
Your order is {this.state.orderAmount} {this.props[categoryName][categoryName][productId].name} chargers for ${this.state.orderPrice}
</Text>
<Button
title='Add to Cart'
color="#f194ff"
onPress={() => this.addToCart(this.state.itemId)}
/>
</ScrollView>
)
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
resizeMode: "contain",
height: 200,
width: 200
},
title: {
fontSize: 32,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(DetailsScreen);
The following code samples are my redux files. I have simplified them with only the cart information for readability.
ActionCreators.js
export const fetchCart = () => (dispatch) => {
dispatch(cartLoading());
return fetch(baseUrl + 'cart')
.then(response => {
if (response.ok) {
return response;
} else {
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
var errmess = new Error(error.message);
throw errmess;
})
.then(response => response.json())
.then(cart => dispatch(addCart(cart)))
.catch(error => dispatch(cartFailed(error.message)));
};
export const cartLoading = () => ({
type: ActionTypes.CART_LOADING
});
export const cartFailed = (errmess) => ({
type: ActionTypes.CART_FAILED,
payload: errmess
});
export const postCart = (id) => (dispatch) => {
const newCart = {
id: id
};
setTimeout(() => {
dispatch(addToCart(newCart));
}, 2000);
};
export const addToCart = (cart) => ({
type: ActionTypes.ADD_TO_CART,
payload: cart
});
export const addCart = (id) => ({
type: ActionTypes.ADD_CART,
payload: id
});
export const removeCart = (id) => ({
type: ActionTypes.REMOVE_CART,
payload: id
});
ActionTypes.js
export const POST_CART = 'POST_CART';
export const ADD_TO_CART = 'ADD_TO_CART';
export const ADD_CART = 'ADD_CART';
export const REMOVE_CART = 'REMOVE_CART';
export const CART_LOADING = 'CART_LOADING';
export const CART_FAILED = 'CART_FAILED';
cart.js
import * as ActionTypes from './ActionTypes';
export const cart = (
state = {
isLoading: true,
errMess: null,
cart:[]
},
action) => {
switch (action.type) {
case ActionTypes.ADD_CART:
return {...state, isLoading: false, errMess: null, cart: action.payload};
case ActionTypes.CART_LOADING:
return {...state, isLoading: true, errMess: null, cart: []};
case ActionTypes.CART_FAILED:
return {...state, isLoading: false, errMess: action.payload};
case ActionTypes.ADD_TO_CART:
var newCart = action.payload;
return {...state, cart: state.cart.concat(newCart) };
default:
return state;
}
};
The following is my db.json file. I have input one item into the cart array for testing but it also does not show up in the cart. Have also simplified this file to only show a few products for readability.
"products": [
{
"id": 0,
"name": "Ezywhip Pro",
"category": "chargers",
"label": "",
"featured": false,
"description": "Ezywhip Pro Cream Chargers, Made by MOSA",
"image": "images/ezywhip.png",
"quantity": 0,
"price": 0
},
{
"id": 1,
"name": "Ezywhip Pro",
"category": "ezy",
"label": "",
"featured": false,
"description": "Ezywhip Pro Cream Chargers, Made by MOSA",
"image": "images/ezywhip.png",
"quantity": 50,
"price": 40
},
{
"id": 2,
"name": "Ezywhip Pro",
"category": "ezy",
"label": "",
"featured": false,
"description": "Ezywhip Pro Cream Chargers, Made by MOSA",
"image": "images/ezywhip.png",
"quantity": 100,
"price": 70
},
{
"id": 3,
"name": "Ezywhip Pro",
"category": "ezy",
"label": "",
"featured": false,
"description": "Ezywhip Pro Cream Chargers, Made by MOSA",
"image": "images/ezywhip.png",
"quantity": 150,
"price": 110
}
],
"cart": [
{
"id": 1
}
]
}
If anyone could explain what I'm doing wrong it would be greatly appreciated.
I got it working by changing the following:
export const addToCart = (id) => ({
type: ActionTypes.ADD_TO_CART,
payload: id
});
Not sure if this was causing any issues but I changed it to id for safe measure.
This is what was causing the main issue, I needed to use el.id to specify that's what I was comparing with in the data.
<FlatList
data={this.props.products.products.filter(product => this.props.carts.carts.some(el => el.id === product.id))}
renderItem={renderMenuItem}
keyExtractor={item => item.id.toString()}
/>

Apex chart doesn't display immediately

I have the following code for a apex chart to be displayed based on value
import React, { Component, Fragment,useState } from "react";
import RestAPI from "services/api";
import axios from "axios";
import Select from 'react-select';
import "d3-transition";
import "tippy.js/dist/tippy.css";
import "tippy.js/animations/scale.css";
/* Chart code */
// Themes begin
// Themes end
import {
Button,
Label,
FormGroup,
Form,
} from "reactstrap";
import ReactApexChart from "react-apexcharts";
import Loader from "react-loader-spinner";
class BarChart extends Component {
constructor(props){
super(props);
this.selectValue=this.selectValue.bind(this)
this.state = {
selectValue:"",
items:[],
weights:[],
isLoaded:true,
showViz:false,
series: [],
options: "",
};
}
selectValue (e) {
var selectValue=this.state.selectValue;
selectValue=e.value;
fetch("http://127.0.0.1:8000/api/values/"+selectValue)
.then(response => response.json())
.then(json => {
this.state.series=[]
var {items,weights}=this.state;
this.setState({
isLoaded:true,
items:json.keywords,
weights:json.weights,
series: [{ name: "Keywords", data: weights }],
options:{
chart: {
type: 'bar',
},
title:{
text:"Top 10 values"
},
plotOptions: {
bar: {
horizontal: true,
}
},
xaxis:{
categories: items
},
grid: {
xaxis: {
show:false,
lines: {
show: false
},
axisTicks:{
show:false,
offsetX: 0,
offsetY: 0
},
axisBorder:{
show:false
}
}
},
yaxis: {
reversed: false,
axisTicks: {
show: false
}
}
},
})
});
this.state.showViz=true;
}
render() {
var {selectValue,items,weights,isLoaded,options,series,showViz}=this.state;
const yeardata = [
{
value: "1",
label: "1"
},
{
value: "2",
label: "2"
},
{
value: "3",
label: "3"
},
{
value: "4",
label: "4"
},
{
value: "5",
label: "5"
},
{
value: "6",
label: "6"
},
{
value: "7",
label: "7"
},
{
value: "8",
label: "8"
},
{
value: "9",
label: "9"
},
{
value: "10",
label: "10"
}
];
//var{items,arr_keys,arr_vals}=this.state;
if(isLoaded){
return (
<>
{ console.log("the values are:",items)}
{ console.log("the values are:",weights)}
{ console.log("the values are:",options)}
{ console.log("the values are:",series)}
<Form role="form" >
<FormGroup>
<h2>Top 10 values</h2>
<Label>Select an Value</Label>
<Select placeholder="Select Option" options={yeardata} value={yeardata.find(obj => obj.value === selectValue)}
onChange={this.selectValue}
/>
<br></br>
{this.state.showViz?(
<ReactApexChart options={this.state.options} series={this.state.series} type="bar" height={250} />):
(<Loader type="Puff">
</Loader>)}
</FormGroup>
</Form>
</>
);
}
else{
return(
<>
</>
)
}
}
}
export default BarChart;
I want to display the chart when I select a value,but it is not displaying.Instead if I select another value,the previous value is displayed.Also,initially a blank plot is rendered which I don't want.Also,the loader is displayed as soon as the page is loaded which I want to avoid too.How could I resolve this?
Screenshot of rendered image:
You never set isLoaded false, so it's always true. You need to set isLoaded to false in constructor and after you receive response - true:
React state is async, you can't set a value just like this this.state.showViz=true; , you need to use this.setState each time you want to change your state and don't forget to put all other state data
this.setState({...this.state, showViz: true});
And as I've understood your logic correctly you need to put this code inside last .then:
this.setState({
isLoaded:true,
items:json.keywords,
weights:json.weights,
showViz: true,
...
You never set selectValue, so you don't need this code var selectValue=this.state.selectValue
Final code:
import React, { Component, Fragment, useState } from "react";
import RestAPI from "services/api";
import axios from "axios";
import Select from "react-select";
import "d3-transition";
import "tippy.js/dist/tippy.css";
import "tippy.js/animations/scale.css";
/* Chart code */
// Themes begin
// Themes end
import { Button, Label, FormGroup, Form } from "reactstrap";
import ReactApexChart from "react-apexcharts";
import Loader from "react-loader-spinner";
class BarChart extends Component {
constructor(props) {
super(props);
this.selectValue = this.selectValue.bind(this);
this.state = {
selectValue: "",
items: [],
weights: [],
isLoaded: true,
showViz: false,
series: [],
options: "",
};
}
selectValue(e) {
var selectValue = this.state.selectValue;
selectValue = e.value;
fetch("http://127.0.0.1:8000/api/values/" + selectValue)
.then((response) => response.json())
.then((json) => {
var { items, weights } = this.state;
this.setState({
isLoaded: true,
items: json.keywords,
weights: json.weights,
showViz: true,
series: [
{
name: "Keywords",
data: weights,
},
],
options: {
chart: {
type: "bar",
},
title: {
text: "Top 10 values",
},
plotOptions: {
bar: {
horizontal: true,
},
},
xaxis: {
categories: items,
},
grid: {
xaxis: {
show: false,
lines: {
show: false,
},
axisTicks: {
show: false,
offsetX: 0,
offsetY: 0,
},
axisBorder: {
show: false,
},
},
},
yaxis: {
reversed: false,
axisTicks: {
show: false,
},
},
},
});
});
}
render() {
var {
selectValue,
items,
weights,
isLoaded,
options,
series,
showViz,
} = this.state;
const yeardata = [
{
value: "1",
label: "1",
},
{
value: "2",
label: "2",
},
{
value: "3",
label: "3",
},
{
value: "4",
label: "4",
},
{
value: "5",
label: "5",
},
{
value: "6",
label: "6",
},
{
value: "7",
label: "7",
},
{
value: "8",
label: "8",
},
{
value: "9",
label: "9",
},
{
value: "10",
label: "10",
},
];
if (isLoaded) {
return (
<>
{console.log("the values are:", items)}
{console.log("the values are:", weights)}
{console.log("the values are:", options)}
{console.log("the values are:", series)}
<Form role="form">
<FormGroup>
<h2> Top 10 values </h2> <Label> Select an Value </Label>
<Select
placeholder="Select Option"
options={yeardata}
value={yeardata.find((obj) => obj.value === selectValue)}
onChange={this.selectValue}
/>
</br>
{this.state.showViz ? (
<ReactApexChart
options={this.state.options}
series={this.state.series}
type="bar"
height={250}
/>
) : (
<Loader type="Puff"></Loader>
)}
</FormGroup>
</Form>
</>
);
} else {
return <></>;
}
}
}

Issue while using react-picky select menu

I have recently downloaded the react-picky and have used it inside a map function to loop through my dynamic data. In the picky i have set multiselect as true.
How ever on the onchange function am getting only the currently selected value and not the list of values selected for picky.
The issue am facing is in the case of multiselect where the value will be a single object containing the current selected item rather than the list of items selected. Could you please help me with the issue. I have tried every possible solution and it does not seem to work.Any help would be really appreciated as am stuck in the issue for sometime.
const sectorsData = [
{
name: "Technology",
options: [
{
id: "1",
name: "AI & Analytics"
},
{
id: "2",
name: "Robotics"
},
{
id: "3",
name: "IoT"
}
]
},
{
name: "Sector",
options: [
{
id: "1",
name: "Automotive"
},
{
id: "2",
name: "Oil and gas"
},
{
id: "3",
name: "Consumer Products"
}
]
},
{
name: "Accounts",
options: [
{
id: "1",
name: "Alphabet Inc."
},
{
id: "2",
name: "General Motors Company"
},
{
id: "3",
name: "Consumer Products"
},
{
id: "4",
name: "State Street Corporation"
}
]
},
{
name: "Region",
options: [
{
id: "1",
name: "Canada Region"
},
{
id: "2",
name: "Central"
},
{
id: "3",
name: "FSO Americas"
},
{
id: "4",
name: "Latam North"
},
{
id: "5",
name: "Latam South"
}
]
}
];
const App = props => {
const [assetsAddedState, setAssetsAddedState] = React.useState({
selectedItems: []
});
const selectedOption = (name, value) => {
setAssetsAddedState(prev => {
return { ...prev, [name]: value };
});
};
return (
<form className="create-work-form-container" noValidate autoComplete="off">
{sectorsData.map((selectItem, i) => (
<Picky
value={assetsAddedState[selectItem.name]}
onChange={selectedOption.bind(this, selectItem.name)}
options={selectItem.options}
placeholder={selectItem.name}
numberDisplayed={1}
valueKey="id"
labelKey="name"
multiple={true}
includeSelectAll={true}
includeFilter={true}
dropdownHeight={600}
className="multiSelectControl "
name={selectItem.name}
/>
))}
</form>
);
};
value should be returning the multiple values user has selected.
See if this is working for you:
Working example on CodeSandbox:
https://codesandbox.io/s/react-pickyanswerso-yp02j
import React from "react";
import { render } from "react-dom";
import Picky from "react-picky";
import "react-picky/dist/picky.css";
const sector1 = {
name: "Technology",
options: [
{
id: "1",
name: "AI & Analytics"
},
{
id: "2",
name: "Robotics"
},
{
id: "3",
name: "IoT"
}
]
};
const sector2 = {
name: "Sector",
options: [
{
id: "4",
name: "Automotive"
},
{
id: "5",
name: "Oil and gas"
},
{
id: "6",
name: "Consumer Products"
}
]
};
const sector3 = {
name: "Accounts",
options: [
{
id: "7",
name: "Alphabet Inc."
},
{
id: "8",
name: "General Motors Company"
},
{
id: "9",
name: "Consumer Products"
},
{
id: "10",
name: "State Street Corporation"
}
]
};
const sector4 = {
name: "Region",
options: [
{
id: "11",
name: "Canada Region"
},
{
id: "12",
name: "Central"
},
{
id: "13",
name: "FSO Americas"
},
{
id: "14",
name: "Latam North"
},
{
id: "15",
name: "Latam South"
}
]
};
const App = props => {
// const [assetsAddedState, setAssetsAddedState] = React.useState([]);
const [selected1, setSelected1] = React.useState([]);
const [selected2, setSelected2] = React.useState([]);
const [selected3, setSelected3] = React.useState([]);
const [selected4, setSelected4] = React.useState([]);
const selectedOption1 = value => {
console.log("VAlue: " + JSON.stringify(value));
setSelected1(value);
};
const selectedOption2 = value => {
console.log("VAlue: " + JSON.stringify(value));
setSelected2(value);
};
const selectedOption3 = value => {
console.log("VAlue: " + JSON.stringify(value));
setSelected3(value);
};
const selectedOption4 = value => {
console.log("VAlue: " + JSON.stringify(value));
setSelected4(value);
};
return (
<form className="create-work-form-container" noValidate autoComplete="off">
<Picky
value={selected1}
onChange={selectedOption1}
options={sector1.options}
placeholder={sector1.name}
numberDisplayed={1}
valueKey="id"
labelKey="name"
multiple={true}
includeSelectAll={true}
includeFilter={true}
dropdownHeight={600}
className="multiSelectControl "
name={sector1.name}
/>
<Picky
value={selected2}
onChange={selectedOption2}
options={sector2.options}
placeholder={sector2.name}
numberDisplayed={1}
valueKey="id"
labelKey="name"
multiple={true}
includeSelectAll={true}
includeFilter={true}
dropdownHeight={600}
className="multiSelectControl "
name={sector2.name}
/>
<Picky
value={selected3}
onChange={selectedOption3}
options={sector3.options}
placeholder={sector3.name}
numberDisplayed={1}
valueKey="id"
labelKey="name"
multiple={true}
includeSelectAll={true}
includeFilter={true}
dropdownHeight={600}
className="multiSelectControl "
name={sector3.name}
/>
<Picky
value={selected4}
onChange={selectedOption4}
options={sector4.options}
placeholder={sector4.name}
numberDisplayed={1}
valueKey="id"
labelKey="name"
multiple={true}
includeSelectAll={true}
includeFilter={true}
dropdownHeight={600}
className="multiSelectControl "
name={sector4.name}
/>
</form>
);
};
render(<App />, document.getElementById("root"));

Resources