How i can update object in array - reactjs

I'd like to know how i can update object in array.
I asked this question before,
and I got the hint at the moment but i can't still figure it out how to update x and y ,
so here is my piece code :
const [data, setdata] = useState([
{ x: 1, y: 2 },
{ x: 1, y: 2 },
{ x: 1, y: 2 },
]);
const x= [3, 4, 5, 6, 7, 8, 9];
const y =[ 1,2,3,4,6,7];
const updateX = () => {
setdata((data) => data.map((d, i) => ({ ...d, x: newData[i] })));
setdata((data) => data.map((d, i) => ({ ...d, y: newData[i] })))
};
/////result ///
{ x: 3, y: 2 },
{ x: 4, y: 2 },
{ x: 5, y: 2 },
/// what i want ///
{ x: 3, y: 1 },
{ x: 4, y: 2 },
{ x: 5, y: 3 },
{ x: 6, y: 4 },
{ x: 7, y: 5 },
{ x: 8, y: 6 },
{ x: 9, y: 7 },

I don't quite understand why you are initializing the data object with those values.
The result you want, you can't get it by iterating the data object that you have initialized with 3 values.
Assuming that the arrays have these values and an equal length, you can try this:
const [data, setdata] = useState([
{ x: 1, y: 2 },
{ x: 1, y: 2 },
{ x: 1, y: 2 }
]);
const x = [3, 4, 5, 6, 7, 8, 9];
const y = [1, 2, 3, 4, 5, 6, 7];
const newData = x.reduce((acc, xVal, index) => {
const obj = { x: xVal, y: y[index] };
acc.push(obj);
return acc;
}, []);
setdata(newData)

Related

Data Array Undefined React Native

I am trying to map the data I get back from an API in this format:
data={[
{ x: 0, y: 0 },
{ x: 1, y: 1 },
{ x: 2, y: 2 },
{ x: 3, y: 3 },
{ x: 4, y: 4 },
]}
I have a get call then I map each of the items to give me an x , y value:
getCryptoChartData('histohour', selectedCrypto, 24, 1).then(
cryptoChartData => {
//const response = cryptoChartData.Data.map(item => item.close);
const data = cryptoChartData.Data.map(item => {
[
{
x: item.time,
y: item.close,
},
];
});
return this.setState({cryptoChartData: data});
},
);
However, I notice that the data array is set to undefined:
<SlideAreaChart
data={this.state.cryptoChartData}
/>
Am I setting the data array correctly with the mapping?
Yes, it seems the problem is in mapping. You just forget to return the generated object:
const data = cryptoChartData.Data.map(item => {
return {
x: item.time,
y: item.close,
};
});
or
const data = cryptoChartData.Data.map(item => ({
x: item.time,
y: item.close,
}));
Final code of getCryptoChartData method will look like:
getCryptoChartData('histohour', selectedCrypto, 24, 1)
.then(cryptoChartData => {
const data = cryptoChartData.Data.map(item => ({
x: item.time,
y: item.close,
}));
this.setState({ cryptoChartData: data });
});

How can I add object in array as value length?

I'd like to know how i can add object in array length.
I asked this question before,
and I got the hint at the moment but i can't still figure it out how to do it ,
so here is my piece code :
const [data, setdata] = useState([
{ x: 1, y: 2 },
{ x: 1, y: 2 },
{ x: 1, y: 2 },
]);
const newData = [3, 4, 5, 6, 7, 8, 9];
const updateX = () => {
setdata((data) => data.map((d, i) => ({ ...d, x: newData[i] })));
};
/////result ///
{ x: 3, y: 2 },
{ x: 4, y: 2 },
{ x: 5, y: 2 },
/// what i want ///
{ x: 3, y: 2 },
{ x: 4, y: 2 },
{ x: 5, y: 2 },
{ x: 6, y: 2 },
{ x: 7, y: 2 },
{ x: 8, y: 2 },
{ x: 9, y: 2 },
The problem here is that you are mapping over data which only has 3 elements. Therefore, the final result will only have 3 elements.
To create a new array from newData, then you must use newData.map() instead of data.map(). The simplest way would be to do it directly:
newData.map(item => {x: item, y: 2})
You can update like this:
const updateX = () => {
setdata(newData.map((item, i) => ({ x: item, y: data[i] ?? 2 })));
};

Rendering vector-tiles using Mapbox using react-mapbox-gl

I have a geoJSON file that I convert into vector.tiles using this npm package.
I use const tileIndex = geojsonvt(geoJSON). The geoJSON file has the following format and it gets converted without any error.
const geoJSON = {
type: 'FeatureCollection',
crs: {
type: 'name',
properties: { name: 'urn:ogc:def:crs:OGC:1.3:CRS84' }
},
features: [
{
properties: [Object],
geometry: [Object],
type: 'Feature',
_id: '5ed7b221a61a4b2970433932'
},
... 1840 more items
]
}
The result (geoJSON vector-tiles) that I get after conversion is following -
const tiles = {
options: {},
tiles: {
'0': {
features: [Array],
numPoints: 540529,
numSimplified: 3,
numFeatures: 1940,
source: null,
x: 0,
y: 0,
z: 0,
transformed: false,
minX: 0.5162953202777778,
minY: 0.316725863688461,
maxX: 0.5338655772222223,
maxY: 0.34955196703359503
},
'1': { ... }
},
tileCoords: [
{ z: 0, x: 0, y: 0 }, { z: 1, x: 1, y: 1 },
{ z: 1, x: 1, y: 0 }, { z: 2, x: 3, y: 1 },
{ z: 2, x: 3, y: 0 }, { z: 2, x: 2, y: 1 },
{ z: 3, x: 5, y: 3 }, { z: 3, x: 5, y: 2 },
{ z: 3, x: 4, y: 3 }, { z: 3, x: 4, y: 2 },
{ z: 4, x: 9, y: 5 }, { z: 4, x: 9, y: 4 },
{ z: 4, x: 8, y: 5 }, { z: 5, x: 17, y: 11 },
{ z: 5, x: 17, y: 10 }, { z: 5, x: 16, y: 11 },
{ z: 5, x: 16, y: 10 }, { z: 4, x: 8, y: 4 },
{ z: 2, x: 2, y: 0 }, { z: 1, x: 0, y: 1 },
{ z: 1, x: 0, y: 0 }
]
}
After converting a huge geoJSON file with 5000 layers into vector tiles, I am sending this data to the client-side wherein I render Map using React.js and Mapbox*. I use following to render the map but I have not been able to figure out what I am doing wrong. The error that I get says error: layers.jsx-layer-0: layer "jsx-layer-0" must specify a "source-layer"
<Source type="vector" tiles={data.tiles} >
<Layer {...dataLayer}/>
</Source>
I went through the documentation of Mapbox for the same but I'm unable to find what I am doing wrong. Any help would be of great help. Thank you very much.
react-mapbox-gl is in many places just a wrapper around mapbox-gl, and if you look at the documentation there:
https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#tiled-sources
You will see that the "tiles" property is only for url sources, where as the "url" property can be used to load a file with tiles:
"url": "http://api.example.com/tilejson.json"
The docs indicate that the source-layer is required field for vector layers.
That said, it certainly opaque as to how this works in a declarative api. Based on example, you might try this to see if it works -
...
const url = 'mapbox://mapbox.mapbox-terrain-v2'
const source = 'my-source';
<Source id={{source}} name={{source}} type="vector" url={url} tiles={data.tiles} >
<Layer source={{source}} {...dataLayer}/>
</Source>
...
rendering a layer with it source so you need to referrer to source id in layer + you need to add a source-layer prop like this:
<Source id='contours' type='vector' url='mapbox://mapbox.mapbox-terrain-v2' tileJsonSource={data.tiles}/>
<Layer
id='contours'
type='line'
source='contours'
source-layer='contour'
paint={{
'line-color': '#877b59',
'line-width': 1
}}
/>
</MapGL>;

React-Grid-Layout elements handle jumps if there are other elements in the app root in react app

My React-Grid-Layout elements handle jumps if there are other elements in the app root in my react app.
If I remove the navbar component above the responsive grid layout I am able to click and drag properly, otherwise, when I try to click on the responsive grid layout element it jumps down.
Here's my code:-
App.js
import React from 'react';
import './App.css';
import '#devexpress/dx-react-grid-bootstrap4/dist/dx-react-grid-bootstrap4.css';
import PyfinNavbar from './components/navbar';
import HomeView from './home';
import PyfinResponsiveGrid from './ResponsiveGridLayout';
function App() {
return (
<div className="App">
<PyfinNavbar></PyfinNavbar>
<HomeView></HomeView>
<PyfinResponsiveGrid></PyfinResponsiveGrid>
</div>
);
}
export default App;
PyfinResponsiveGridLayout.jsx
import React from "react";
import { Responsive as ResponsiveGridLayout } from "react-grid-layout";
import PyfinGrid from "./grid";
let layouts = {
lg: [
{ h: 2, w: 2, x: 0, y: 0 },
{ h: 2, w: 2, x: 1, y: 0 },
{ h: 2, w: 2, x: 2, y: 0 },
{ h: 2, w: 2, x: 3, y: 0 }
],
sm: [
{ h: 2, w: 2, x: 0, y: 0 },
{ h: 2, w: 2, x: 1, y: 0 },
{ h: 2, w: 2, x: 2, y: 0 },
{ h: 2, w: 2, x: 3, y: 0 }
],
md: [
{ h: 2, w: 2, x: 0, y: 0 },
{ h: 2, w: 2, x: 1, y: 0 },
{ h: 2, w: 2, x: 2, y: 0 },
{ h: 2, w: 2, x: 3, y: 0 }
],
xs: [
{ h: 2, w: 2, x: 0, y: 0 },
{ h: 2, w: 2, x: 0, y: 1 },
{ h: 2, w: 2, x: 0, y: 2 },
{ h: 2, w: 2, x: 0, y: 3 }
],
xxs: [
{ h: 2, w: 2, x: 0, y: 0 },
{ h: 2, w: 2, x: 0, y: 1 },
{ h: 2, w: 2, x: 0, y: 2 },
{ h: 2, w: 2, x: 0, y: 3 }
]
};
class PyfinResponsiveGrid extends React.Component {
render() {
return (
<ResponsiveGridLayout
className="layout"
layouts={layouts}
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
>
<div className="widgetborder" key="1">
<PyfinGrid></PyfinGrid>
</div>
</ResponsiveGridLayout>
);
}
}
export default PyfinResponsiveGrid;
grid.jsx
import React from "react";
import { PagingState, IntegratedPaging } from "#devexpress/dx-react-grid";
import {
Grid,
Table,
TableHeaderRow,
PagingPanel
} from "#devexpress/dx-react-grid-bootstrap4";
import customers from "./customers";
const GridView = () => (
<Grid
rows={customers}
columns={[
{ name: "customerID", title: "ID" },
{ name: "companyName", title: "Company" },
{ name: "contactName", title: "Name" },
{ name: "contactTitle", title: "Title" },
{ name: "address", title: "Address" }
]}
>
<PagingState defaultCurrentPage={0} pageSize={1} />
<IntegratedPaging />
<Table />
<TableHeaderRow />
<PagingPanel />
</Grid>
);
class PyfinGrid extends React.Component {
state = {};
render() {
return (
<div>
<GridView></GridView>
</div>
);
}
}
export default PyfinGrid;
Basically I am trying to create something like
https://www.bitmex.com/app/trade/XRPH20
It uses the same gridlayout control but when I use devextreme react grid in the layout the above mentioned problem happens.
This solved the issue for me - see comment.
.react-grid-layout {
position: relative;
}

How to show hover state for 1 card element that has handler event attached to multiple card elements?

I'm a React beginner, trying to build a dashboard with card components. I have a React component that renders card elements, and for each card, has the same handler events for mouseenter and mouseleave. The expected behavior is to see :hover styles for when a mouse hovers over one widget. However, I'm seeming ALL the widgets with the :hover style. How can I change the code, so that only one that is moused over shows the hover state, and not all?
class Board extends Component {
constructor(props) {
super(props) {
this.showHoverBorder = this.showHoverBorder.bind(this);
this.hideHoverBorder = this.hideHoverBorder.bind(this);
this.state = {
isHoverStyleOn: false,
layouts: {
lg: [
{ i: "a", x: 0, y: 0, w: 1, h: 1 },
{ i: "b", x: 2, y: 0, w: 1, h: 1 },
{ i: "c", x: 2, y: 0, w: 1, h: 1 },
{ i: "d", x: 3, y: 0, w: 1, h: 1 },
{ i: "e", x: 0, y: 1, w: 1, h: 1 },
{ i: "f", x: 0, y: 1, w: 1, h: 1 }
]}
}
showHoverBorder() {
this.setState({ isHoverStyleOn: true })
}
hideHoverBorder(hmm) {
this.setState({ isHoverStyleOn: false })
}
}
render() {
let widget = "widget";
if(this.state.isHoverStyleOn) {
widget += ' widget-hover';
} else { widget = "widget"; }
return (
<div layouts={this.state.layouts}>
{this.state.layouts.lg.map((w) => ((
<div key={w.i} className={widget}>
<div className="widget-body">
<div className="widget-bar" onMouseEnter={this.showHoverBorder} onMouseLeave={this.hideHoverBorder}>
</div>
<div className="widget-graph"></div>
</div>
</div>
)))}
</div>
)
}
}
export default Board;
I'd suggest that you extract the single items into a new class where you can handle the hover state as you want like this:
class App extends Component {
constructor(props) {
super(props);
this.state = {
isHoverStyleOn: false,
layouts: {
lg: [
{ i: "a", x: 0, y: 0, w: 1, h: 1 },
{ i: "b", x: 2, y: 0, w: 1, h: 1 },
{ i: "c", x: 2, y: 0, w: 1, h: 1 },
{ i: "d", x: 3, y: 0, w: 1, h: 1 },
{ i: "e", x: 0, y: 1, w: 1, h: 1 },
{ i: "f", x: 0, y: 1, w: 1, h: 1 }
]
}
};
}
render() {
return (
<div layouts={this.state.layouts}>
{this.state.layouts.lg.map(w => (
<Item w={w} />
))}
</div>
);
}
}
Extracted Item-Component
class Item extends Component {
state = {
active: false
};
hover = () => {
this.setState({
active: !this.state.active
});
};
render() {
const { w } = this.props;
const { active } = this.state;
return (
<div key={w.i} className={!active ? "widget" : "widget widget-hover"}>
<div className="widget-body">
<div
className="widget-bar"
onMouseEnter={() => this.hover()}
onMouseLeave={() => this.hover()}
>
<h1>test</h1>
</div>
<div className="widget-graph" />
</div>
</div>
);
}
}

Resources