I'm trying to update the two child components on a button click. Since I'm passing functions to the child component I'm able to change the state. but the issue is state changes are not reflected on both child components. <AssetsTable/>
is changing on state changes while <CryptoPieChart/>
doesn't
<Card>
<CardBody>
<div className="block w-full ">
{this.state.Assets.length > 0 ? (
<div className="grid ml-8 md:grid-cols-2 items-center">
<div className="min-w-0">
<AssetsTable
Assets={this.state.Assets}
onDelete={this.onDeleteAsset}
onRefresh={this.onRefreshAsset}
/>
</div>
<div className="mx-2 flex flex-col items-center min-w-0">
<p className="text-xl font-semibold text-gray-800 dark:text-gray-300">
Token Distribution
</p>
<CryptoPieChart
className="w-full"
Assets={this.state.Assets}
/>
</div>
</div>
) : (
""
)}
</div>
</CardBody>
</Card>
<AssetTable/>
code
import React from "react";
import {
Table,
TableCell,
TableBody,
TableRow,
TableContainer,
Button,
} from "@windmill/react-ui";
import { EditIcon, TrashIcon, RefreshIcon } from "../../icons";
class AssetsTable extends React.Component {
constructor(props) {
super(props);
}
async componentDidMount() {}
render() {
return (
<>
<TableContainer className="mb-8">
<Table>
<TableBody>
{this.props.Assets.map((asset, i) => (
<TableRow key={i}>
<TableCell className="">
<div className="flex items-center text-sm border-0">
<div className="relative rounded-full inline-block w-8 h-8 hidden mr-3 md:block">
<img
className="object-cover rounded-circle circular-square "
src={asset.image}
alt="asset"
loading="lazy"
/>
<div
className="absolute inset-0 rounded-full"
aria-hidden="true"
></div>
</div>
<div>
<div className="font-semibold ">{asset.symbol}</div>
<p className="text-xs text-gray-600 dark:text-gray-400">
{asset.quantity} {asset.symbol}
{" * "}
{asset.current_price}
</p>
</div>
</div>
</TableCell>
<TableCell>
<span className="text-sm">$ {asset.usdValue}</span>
</TableCell>
<TableCell>
<div className="flex items-center space-x-4">
<Button
layout="link"
size="icon"
aria-label="Edit"
value={i}
onClick={this.props.onRefresh}
>
<RefreshIcon className="w-5 h-5" aria-hidden="true" />
</Button>
{i > 0 ? (
<Button
layout="link"
size="icon"
aria-label="Delete"
value={i}
onClick={this.props.onDelete}
>
<TrashIcon className="w-5 h-5" aria-hidden="true" />
</Button>
) : null}
</div>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</>
);
}
}
export default AssetsTable;
<CryptoPieChart/>
Code
import React from "react";
import Chart from "react-google-charts";
import { getScrtProvider } from "../../apis/scrt";
class CryptoPieChart extends React.Component {
constructor(props) {
super(props);
this.state = {
chartData: [],
};
this.RecreateDataArray();
}
async RecreateDataArray() {
const wallet = await getScrtProvider();
let dataArray = [];
let total = this.props.Assets.length;
let i;
dataArray.push(["symbol", "value"]);
for (i = 0; i < total; i) {
if (this.props.Assets[i].address !== wallet.address) {
continue;
}
let totalValue =
this.props.Assets[i].current_price * this.props.Assets[i].quantity;
dataArray.push([this.props.Assets[i].symbol, totalValue]);
}
this.setState({ chartData: dataArray });
}
render() {
return (
<Chart
width={"300px"}
height={"300px"}
chartType="PieChart"
loader={<div>Loading Chart</div>}
data={this.state.chartData}
options={{
legend: "none",
pieSliceText: "label",
colors: [
"#024678",
"#8accfd",
"#7CB7E3",
"#6EA3CA",
"#608EB1",
"#527A97",
"#45657E",
"#375165",
],
backgroundColor: {
fill: "#000000",
fillOpacity: 0.0,
},
}}
rootProps={{ "data-testid": "5" }}
/>
);
}
}
export default CryptoPieChart;
I don't see any difference. Please help
CodePudding user response:
You only call RecreateDataArray
when the component mounts, not when props change.
That's why it doesn't update when your props change.
You could do that update with a componentWillUpdate
lifecycle method, but it will be a lot easier to just refactor to a function component and use the useEffect
hook instead:
import React from "react";
import Chart from "react-google-charts";
import { getScrtProvider } from "../../apis/scrt";
async function RecreateDataArray(assets) {
const wallet = await getScrtProvider();
let dataArray = [];
let total = assets.length;
let i;
dataArray.push(["symbol", "value"]);
for (i = 0; i < total; i) {
if (assets[i].address !== wallet.address) {
continue;
}
let totalValue = assets[i].current_price * assets[i].quantity;
dataArray.push([assets[i].symbol, totalValue]);
}
return dataArray;
}
function CryptoPieChart({ Assets }) {
const [chartData, setChartData] = React.useState([]);
React.useEffect(() => {
RecreateDataArray(Assets).then(setChartData);
}, [Assets]);
return (
<Chart
width={"300px"}
height={"300px"}
chartType="PieChart"
loader={<div>Loading Chart</div>}
data={chartData}
options={{
legend: "none",
pieSliceText: "label",
colors: [
"#024678",
"#8accfd",
"#7CB7E3",
"#6EA3CA",
"#608EB1",
"#527A97",
"#45657E",
"#375165",
],
backgroundColor: {
fill: "#000000",
fillOpacity: 0.0,
},
}}
rootProps={{ "data-testid": "5" }}
/>
);
}
export default CryptoPieChart;