Reputation: 141
I'm trying to pass setChart
to ChartType
and i want to update setChart
in ChartType
component.
so I tried to use array with null, but for some reason, I get this error : TypeError: setChart is not a function
so How can I update setChart
to change the chart with a different div ??
ChartTypePage
const ChartTypePage = ({ changeLayout }) => {
const [chart, setChart] = useState([
null,
null,
null,
null,
null,
null,
null,
null,
]);
const layout = [
<Side id="first" key="a" onClick={chartItself}>
<ChartType visible={visible[0]} setChart={setChart[0]} />
{chart[0]}
</Side>,
<Side id="second" key="b" onClick={chartItself}>
<ChartType visible={visible[1]} setChart={setChart[1]} />
{chart[1]}
</Side>,
<Side id="third" key="c" onClick={chartItself}>
<ChartType visible={visible[2]} setChart={setChart[2]} />
{chart[2]}
</Side>,
ChartType
const ChartType = ({ visible, setChart }) => {
const chartType = [
<Bar
key="p"
data={chartData}
options={{ responsive: true, maintainAspectRatio: false }}
/>,
<Line
key="p"
data={chartData}
options={{ responsive: true, maintainAspectRatio: false }}
/>,
<Radar
key="p"
data={chartData}
options={{ responsive: true, maintainAspectRatio: false }}
/>]
return (
<TypeBox visible={visible}>
<div>
<div onClick={() => setChart(chartType[0])}>
<h3>Line</h3>
</div>
<div onClick={() => setChart(chartType[1])}>
<h3>Bar</h3>
</div>
<div onClick={() => setChart(chartType[2])}>
<h3>Radar</h3>
</div>
<div onClick={() => setChart(chartType[3])}>
<h3>Pie</h3>
</div>
</div>
</TypeBox>
);
};
export default ChartType;
Upvotes: 0
Views: 68
Reputation: 202751
The issue here is that setChart
in the ChartTypePage
parent component is a function, so setChart[0]
doesn't make any sense, it's undefined.
From what I can tell it seems like you want to pass a callback to the ChartType
child component, setChart={setChart}
. This is the state updater function that the children are invoking on click
.
const layout = [
<Side id="first" key="a" onClick={chartItself}>
<ChartType visible={visible[0]} setChart={setChart} />
{chart[0]}
</Side>,
...
];
In the child component you are mutating the state invariant from an array (where chart[i]
is null) to the type of chartType[j]
. You likely really want to update a specific index in the chart
array.
Example:
<div
onClick={() => setChart(charts => charts.map(
(chart, i) => i === 0 ? chartType[0] : chart,
)}
>
<h3>Line</h3>
</div>
This will lead to a lot of code duplication since each onClick
callback function will essentially be the same except for the index you want to update. Abstract this into a function and define it in the parent and pass instead of the setChart
callback.
Example:
This is a curried function that first takes an index to close over in scope and return a function that then takes a char type to also close over in scope and then finally return a function to be used as the attached callback.
Note how the index is closed over when passing to the child, and then the child closes over the chart type.
const updateChart = index => chartType => () => {
setChart(charts => charts.map(
(chart, i) => i === index ? chartType : chart,
);
};
...
const layout = [
<Side id="first" key="a" onClick={chartItself}>
<ChartType visible={visible[0]} setChart={updateChart(0)} />
{chart[0]}
</Side>,
...
];
Child
<div onClick={setChart(chartType[0])}>
<h3>Line</h3>
</div>
Upvotes: 1