Reputation: 11
I'm confused as to how to handle this situation in React.
I have some chart components in a set of tabs. The charts will render or not depending on their permission prop. We check if the user has access to that chart, and if not, it doesn't render. Simple enough.
Now I've been asked to make the parent tab hide if none of the child charts have permission, i.e. if none of them render, hide the tab completely.
Now, I want to do this properly in React, so I understand that data should flow from parent to child - the parent should decide if the child renders. But the permission ID is attached to each child chart - I would need to get each permission, check them and render only if any access to the children was authorised. But that way, isn't data flowing from child to parent?
Greatly appreciate any kind of prods in the right direction.
Upvotes: 1
Views: 2271
Reputation: 6547
Here is my take:
According to React
principles, your data SHOULD flow from Parent to Child. Your parents should be the smart components, make decisions and children should be dumb always.
So the solution to your problem is as follows. Follow this flow
Here is the hierarchy your data should follow:
TABGROUP -> TAB(s) -> CHART(s)
Each tab should take in a list of charts to render. Each chart should take in appropriate props for it to render.
Now before sending in the list of charts to render to each tab, you should check for the condition that at least one chart is permissible to be drawn.
Let us consider your data store returns a JSON
(if it does not, you can restructure data into a similar philosophy). You should fetch data before rendering (by maintaining states, you can lookup some AJAX sample if you are not sure what to do).
var data = {
'tab1': [
{
'id': 'chart1',
'permission': true,
'data': { ... }
},
...
],
'tab2': [
{
'id': 'chartn',
'permission': false,
'data': { ... }
},
...
],
...
}
Now let us try to filter the data as follows,
for (var tab in data) {
data[tab] = data[tab].map(function(chart) {
return chart.permission === true;
});
if (data[tab].length < 1) {
delete data[tab];
}
}
And now that we have filtered data, let is render our components,
// the variable was "data"
<TabGroup>
{
Object.keys(data).map(function(tab, i) {
// tab is a list
return <Tab key={i} charts={tab} />;
})
}
</TabGroup>
Now in your Tab
component,
// incoming prop was charts, so in your render function
<div>
this.props.charts.map(function(chart, i) {
// chart is a JSON object as above
return <Chart key={i} chartData={chart} />;
});
</div>
And eventually you can process the chartData in your Chart
component.
Upvotes: 1