I have the following code I have a cards
state variable using useState, I have atttempted to add my array above to it, but it just adds an empty array, I wasn't able to put the state inside of the if becuase then my variable was undefined. I tried wrapping everything beflow the state and the state in the if , but the then I get some return issues. So the focus is passing into the useState(stateReplace)
Any help would be great
import React, { useState, useCallback, useEffect, useMemo } from "react";
import { Card } from "./Card";
import update from "immutability-helper";
import { LeadsBuilderCollection } from "../../api/LeadsCollection";
import { useTracker } from "meteor/react-meteor-data";
const style = {
width: 400,
};
export const Container = ({ params }) => {
const { leadsBuilder, isLoading } = useTracker(() => {
const noDataAvailable = { leadsBuilder: [] };
if (!Meteor.user()) {
return noDataAvailable;
}
const handler = Meteor.subscribe("leadsBuilder");
if (!handler.ready()) {
return { ...noDataAvailable, isLoading: true };
}
const leadsBuilder = LeadsBuilderCollection.findOne({ _id: params._id });
return { leadsBuilder };
});
const [cards, setCards] = useState([]);
let stateReplace = useMemo(() => {
if (!isLoading && leadsBuilder?.inputs?.length) {
leadsBuilder.inputs.map((leadInput, i) => {
({ id: i, text: leadInput.name });
});
}
return [];
}, [isLoading, leadsBuilder]);
useEffect(() => {
setCards(stateReplace);
}, [setCards, stateReplace]);
const moveCard = useCallback(
(dragIndex, hoverIndex) => {
const dragCard = cards[dragIndex];
setCards(
update(cards, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragCard],
],
})
);
},
[cards]
);
const renderCard = (card, index) => {
return (
<>
{isLoading ? (
<div className="loading">loading...</div>
) : (
<>
<Card
key={card.id}
index={index}
id={card.id}
text={card.text}
moveCard={moveCard}
/>
</>
)}
</>
);
};
return (
<>
{isLoading ? (
<div className="loading">loading...</div>
) : (
<>
<div style={style}>{cards.map((card, i) => renderCard(card, i))}</div>
</>
)}
</>
);
};
Update: I can get it to run if I place a setState in a useEffect but then I get a warning and the drag and drop doesnt work
useEffect(() => {
setCards(stateReplace);
});
Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
Update #2
const [cards, setCards] = useState([]);
let stateReplace = useMemo(() => {
console.log("memo");
if (!isLoading && leadsBuilder?.inputs?.length) {
return leadsBuilder.inputs.map((leadInput, i) => {
({ id: i, text: leadInput.name });
});
}
return [];
}, [isLoading]);
console.log(stateReplace);
useEffect(() => {
setCards(stateReplace);
console.log(setCards);
}, [setCards, stateReplace]);
current output
(4) [undefined, undefined, undefined, undefined]
memo
cannot read propery `id`
i would do it like that
//for preveting updates of memo if ledsBulder will changes on each render
const leadsBuilderRef = useRef(leadsBuilder)
let stateReplace = useMemo(()=>{
if (!isLoading && leadsBuilder.current?.inputs?.length) {
return leadsBuilder.current.inputs.map((leadInput, i) => {
return { id: i, text: leadInput.name };
});
}
return []
}, [isLoading, leadsBuilderRef]);
and then
useEffect(() => {
setCards(stateReplace);
}, [setCards, stateRepalce]);