I'm currently building a page with a ton of Charts, and I'm using a Material UI menu to kinda switch around graphs.
When I click on a new MenuItem it changes my part state and displays a new array of components.
My main problem right now is that whenever I click on the button, all the charts do a quick load, but with this amount of charts this is a problem.
I've tried debugging it, but to be honest I couldn't find a problem, all my states are set when they need to be set, and useEffects are running just once on the beginning, so no extra loads.
This is what it looks like:
And this would be the code that I'm currently rendering. If you need any further info from my code just let me know and if you can provide any advice for the improvement of my code I would be glad, thanks.
<>
<div className={classes.actionBar}>
<SelectEstimatedMonthForm />
</div>
<div>
<Card>
<div>
<h1>Gráficos de DRE</h1>
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
>
Open Menu
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Todos Gráficos</MenuItem>
<MenuItem onClick={handleClose}>
Gráficos DRE Orçamento Evolução
</MenuItem>
<MenuItem onClick={handleClose}>
Gráficos de Evolução Parte 2
</MenuItem>
<MenuItem onClick={handleClose}>
Gráficos de Representatividade
</MenuItem>
</Menu>
</div>
<div>
{chartDataPart?.part1 && part === 1 && values && (
<div>
{chartDataPart?.part1?.map((data) => {
if (data?.type === "bar") {
return (
<div>
{data?.labels && (
<ChartBar
data={data}
text={data?.text}
noLabel={data?.noLabel}
stacked={data?.stacked}
newPlugin={data?.customPlugin}
/>
)}
</div>
);
} else if (data?.type === "pie") {
return (
<div>
{data?.labels && (
<ChartPie text={data?.text} data={data} />
)}
</div>
);
} else if (data?.type === "doughnut") {
return (
<div>
{data?.labels && (
<ChartDoughnut text={data?.text} data={data} />
)}
</div>
);
} else {
return (
<div>
<h1>{data?.text} esta sem type</h1>
</div>
);
}
})}
</div>
)}
{chartDataPart?.part2 && part === 2 && values && (
<div>
{chartDataPart?.part2?.map((data) => {
if (data?.type === "bar") {
return (
<div>
{data?.labels && (
<ChartBar
data={data}
text={data?.text}
noLabel={data?.noLabel}
stacked={data?.stacked}
newPlugin={data?.customPlugin}
/>
)}
</div>
);
} else if (data?.type === "pie") {
return (
<div>
{data?.labels && (
<ChartPie text={data?.text} data={data} />
)}
</div>
);
} else if (data?.type === "doughnut") {
return (
<div>
{data?.labels && (
<ChartDoughnut text={data?.text} data={data} />
)}
</div>
);
} else {
return (
<div>
<h1>{data?.text} esta sem type</h1>
</div>
);
}
})}
</div>
)}
{chartDataPart?.part3 && part === 3 && values && (
<div>
{chartDataPart?.part3?.map((data) => {
if (data?.type === "bar") {
return (
<div>
{data?.labels && (
<ChartBar
data={data}
text={data?.text}
noLabel={data?.noLabel}
stacked={data?.stacked}
newPlugin={data?.customPlugin}
/>
)}
</div>
);
} else if (data?.type === "pie") {
return (
<div>
{data?.labels && (
<ChartPie text={data?.text} data={data} />
)}
</div>
);
} else if (data?.type === "doughnut") {
return (
<div>
{data?.labels && (
<ChartDoughnut text={data?.text} data={data} />
)}
</div>
);
} else {
return (
<div>
<h1>{data?.text} esta sem type</h1>
</div>
);
}
})}
</div>
)}
{chartData && part === 0 && values && (
<div>
{chartData?.map((data) => {
if (data?.type === "bar") {
return (
<div>
{data?.labels && (
<ChartBar
data={data}
text={data?.text}
noLabel={data?.noLabel}
stacked={data?.stacked}
newPlugin={data?.customPlugin}
/>
)}
</div>
);
} else if (data?.type === "pie") {
return (
<div>
{data?.labels && (
<ChartPie text={data?.text} data={data} />
)}
</div>
);
} else if (data?.type === "doughnut") {
return (
<div>
{data?.labels && (
<ChartDoughnut text={data?.text} data={data} />
)}
</div>
);
} else {
return (
<div>
<h1>{data?.text} esta sem type</h1>
</div>
);
}
})}
</div>
)}
</div>
</Card>
</div>
</>
useEffect(() => {
const fetchDreData = async () => {
try {
const res = await http.get(
`call1`
);
const data = await res.data;
const final = data.data;
// console.log(final);
setEstimatedMonths(final);
} catch (e) {
console.log("error", e);
}
};
const fetchProductsData = async () => {
try {
const res = await http.get(
`call2`
);
const data = await res.data;
const final = data.data;
// console.log(res);
setEstimatedProducts(final);
} catch (e) {
console.log("error", e);
}
};
fetchDreData();
fetchProductsData();
// console.log("useffect1");
}, [estimatedMonthContext.monthId]);
useEffect(() => {
if (estimatedProducts && estimatedMonths) {
// console.log("useffect2");
flatData();
}
// productsFlatData();
}, [estimatedProducts, estimatedMonths]);
useLayoutEffect(() => {
// if (values) {
chart();
// console.log("useffect3");
// }
}, [values]);
Something on your page is causing the page to rerender again after load, which would be either a state change or most likely the useEffect.
If you are using useEffect make sure you're doing it correctly by 1. not updating state inside it or 2. returning '[]'.
useEffect(() => {
}, []) // this part here
Along with that you're fetching data from multiple endpoints and each time updating the state every time the data returns, which will cause the page to rerender multiple times. Instead you should move each component to their own respective individual components and fetch their own data individually so they don't affect each other and update the whole page.
Related
I have a component where I need to pass a HTML element as a prop to another element
const MyText = () => {
return (
<>
<h1>Sample heading</h1>
</>
)
}
return (
<div>
<MyComponent Text={MyText} onClose={() => setShow(false)} show={show} />
</div>
);
MyComponent.js
export default function MyComponent(props) {
return (
<>
{props.Text}
</>
);
}
Issue: I'm not getting anything rendered on the screen. Am I missing something here?
There are two ways.
Option 1: Passing a component type (or class if you are coming from OOP background)
const MyText = () => {
return (
<>
<h1>Sample heading</h1>
</>
)
}
return (
<div>
<MyComponent Text={MyText} onClose={() => setShow(false)} show={show} />
</div>
);
const MyComponent = ({ Text }) => {
return (
<>
<Text />
</>
);
}
Option 2: Passing a component (or instance if you are coming from OOP background)
const MyText = () => {
return (
<>
<h1>Sample heading</h1>
</>
)
}
return (
<div>
<MyComponent text={<MyText />} onClose={() => setShow(false)} show={show} />
</div>
);
const MyComponent = ({ text }) => {
return (
<>
{text}
</>
);
}
React spring auto height not working properly.
I am trying to create animation for auto height with react spring, I already achieved the animation but if I go to another page and go back to the page that I have auto height animation it's not working until I refresh the page. How can I fix this problem?
Here is my code:
const defaultHeight = "100px";
const [contentHeight, setContentHeight] = useState(defaultHeight);
const [ref, { height }] = useMeasure();
const expand = useSpring({
config: { ...config.default, duration: 250 },
height: `${contentHeight}px` || defaultHeight,
});
useEffect(() => {
setContentHeight(height);
window.addEventListener("resize", setContentHeight(height));
return window.removeEventListener("resize", setContentHeight(height));
}, [height]);
return (
<div className="team-management">
<div className="team-management-tabs-header">
<div className="team-management-tab-items">
{tabs.map((tab, index) => (
<div
id={editable === true ? "" : `${tab}`}
className={
activeTab === index
? "team-management-tab-item selected"
: "team-management-tab-item"
}
key={tab}
role="button"
tabIndex={tab}
onKeyPress={() => {
return;
}}
onClick={() => {
if (editable === true) {
setActiveTab(index);
} else if (index !== 5 && index !== 6) {
setActiveTab(index);
}
}}
>
{teamData.type === "organization" ? (
<span className="tab-item-text">{tab}</span>
) : (
<>
{tab !== "Sub-Team" && (
<span className="tab-item-text">{tab}</span>
)}
</>
)}
<span className="tab-item-indicator" />
</div>
))}
</div>
</div>
<animated.div style={expand}>
<div className="team-management-tab-panes" ref={ref}>
{tabs[activeTab] === "Mission" && (
<Mission
editable={editable}
teamId={teamId}
teamData={teamData}
fetchTeamData={fetchTeamData}
notify={notify}
/>
)}
{tabs[activeTab] === "Managers" && <Managers members={members} />}
{tabs[activeTab] === "Members" && (
<Members
members={members}
teamId={teamId}
tab={tabs[activeTab]}
userPublicId={userPublicId}
fetchTeamData={fetchTeamData}
notify={notify}
/>
)}
{tabs[activeTab] === "Invitees" && (
<Invitees
teamData={teamData}
teamId={teamId}
privateTeamId={teamData.id}
fetchTeamData={fetchTeamData}
tab={tabs[activeTab]}
/>
)}
{tabs[activeTab] === "Sub-Team" && (
<SubTeam
teamId={teamId}
teamData={teamData}
members={members}
fetchTeamData={fetchTeamData}
/>
)}
</div>
</animated.div>
</div>
);
Thank you for helping me out
Can anyone pls help me out with this problem?
const Users = ({ users, loading }) => {
if (loading) {
return <Spinner />
} else {
return (
<div style={userStyle}>
{users.map((user) => (
<UserItem key={users.id} user={user} />
))}
</div>
)
}
}
use conditional operator && on before map
const Users = ({ users, loading }) => {
if (loading) {
return <Spinner />
} else {
return (
<div style={userStyle}>
{users && users.map((user) => (
<UserItem key={user.id} user={user} />
))}
</div>
)
}
}
Inside the map, you should use user not users so the code will be
{ users.map((user) => (
<UserItem key={user.id} user={user} />
))}
Because, you are passing user as a argument for callback function not users.
I want to prevent that when I click on several items, I have several items (expand: "true")
I would like that when I click on a new item, the old one goes back to its original state (expand: "false")
However, I did not find any property in the documentation to handle this.
https://material-ui.com/components/tree-view/
{stoMenu && (
<TreeView
style={layout.menu}
defaultCollapseIcon={<KeyboardArrowUpIcon />}
defaultExpandIcon={<KeyboardArrowDownIcon />}
>
{stoMenu.root.children.map(menu => {
return (
<TreeItem
key={menu.nodeId}
nodeId={menu.nodeId}
label={
<ListItem
style={layout.menuListItem}
className={menu.iconCls}
>
<ListItemText
style={layout.menuText}
primary={menu.text}
onClick={() => {
if (menu.id === '/accueil') {
this.props.history.push(menu.id);
}
}}
/>
</ListItem>
}
>
{menu.children.map(child => {
return (
<TreeItem
// style={layout.subMenuText}
className={classes.subMenu}
key={child.nodeId}
nodeId={child.nodeId}
label={child.text}
onClick={() => {
if (child.id) {
this.props.history.push(child.id);
}
}}
/>
);
})}
</TreeItem>
);
})}
</TreeView>
)}
I am trying to update the list when my redux store changes but for some odd reason it isn't. I have to manually refresh the page to see my changes. Here's the snippet of my List component and rowRenderer.
<InfiniteLoader
isRowLoaded={this._isRowLoaded}
loadMoreRows={this._loadMoreRows}
rowCount={visibleRequest.length}
>
{({ onRowsRendered, registerChild }) => (
<AutoSizer>
{({ height, width }) => (
<List
ref={registerChild}
className="List"
height={height}
rowHeight={listRowHeight}
onRowsRendered={onRowsRendered}
rowCount={rowCount}
rowRenderer={this._rowRenderer}
width={width}
/>
)}
</AutoSizer>
)}
</InfiniteLoader>
_rowRenderer = ({ index, key, style }) => {
const { loadedRowsMap, selected } = this.state;
const row = this.getDatum(index);
let content;
if (loadedRowsMap[index] === STATUS_LOADED) {
content = row;
} else {
content = (
<div className="placeholder" style={{ width: _.random(100, 200) }} />
);
}
return (
<PendingChat
key={key}
content={content}
style={style}
row={row}
{...this.props}
/>
);
};
Yeah, I ran into the same problem. Its because the references to your objects don't change when you do
const row = this.getDatum(index);
let content;
if (loadedRowsMap[index] === STATUS_LOADED) {
content = row;
}
Take a look at immutability.