I have a React app. There are components rendered from mapped data like the following:
function App () {
const [price, setPrice] = useState(1);
const cardDetails = [
{
id: 1,
title: 'card 1',
setPrice: setPrice
},
{
id: 2,
title: 'card 2',
setPrice: setPrice
}
]
const renderCards = (cardDetails) => {
return (
cardDetails.map((c) => {
<Card cardData={c} />
})
)
};
return (
<>
{renderCards(cardDetails)}
</>
)
}
It's working well. Now I'd like to move the cardDetails
data into a JSON file. I defined the following cardDetails.js
:
export const cardDetails = [
{
id: 1,
title: 'card 1',
setPrice: setPrice
},
{
id: 2,
title: 'card 2',
setPrice: setPrice
}
]
However, I can't pass function setPrice
in the JSON file, any idea what I could do to use the external JSON file?
CodePudding user response:
Since the setPrice
function only exists in App
, it can't be in the separate file. You asked "How to store a function name in JSON?" and while you could do that (setPrice: "setPrice"
, and then when mapping the cards replace it with the setPrice
function), it doesn't really buy you anything.
But it's simple to have App
add it to the cards as it's passing them to the Card
component: <Card cardData={{ ...c, setPrice }} />
That uses spread syntax to spread out the object from c
into a new object and adds setPrice
to the new object.
To avoid creating new objects on every render (which might force Card
to re-render unnecessarily, if Card
is memoized), we can use useMemo
to memoize the array of extended cards like this:
const fullCards = useMemo(() => (
cardDetails.map((card) => ({...card, setPrice}))
), [cardDetails]);
...and then use fullCards
for the map
.
Full version:
In cardDetails.js
:
export const cardDetails = [
{
id: 1,
title: "card 1",
},
{
id: 2,
title: "card 2",
},
];
Your component:
import { cardDetails } from "./cardDetails.js";
function App() {
const [price, setPrice] = useState(1);
const fullCards = useMemo(() => (
cardDetails.map((card) => ({...card, setPrice}))
), [cardDetails]);
const renderCards = (cardDetails) => cardDetails.map((c) => {
<Card key={c.id} cardData={c} />;
});
return renderCards(fullCards);
}
Or simply:
function App() {
const [price, setPrice] = useState(1);
const fullCards = useMemo(() => (
cardDetails.map((card) => ({...card, setPrice}))
), [cardDetails]);
return fullCards.map((c) => {
<Card key={c.id} cardData={c} />;
});
}
Note that I added the key
prop to the Card
elements. You need a key on elements in arrays; details in the React documentation here.
That would also work just fine if you wanted to store the data in a JSON file like:
[
{
"id:: 1,
"title": "card 1",
},
{
"id": 2,
"title": "card 2",
},
]
...and then load and parse that JSON for use in App
.
CodePudding user response:
You don't need to store in JSON you can pass directly to component This is the way we do pass props in react and more optimised solution
const cardDetails = [
{
id: 1,
title: 'card 1'
},
{
id: 2,
title: 'card 2',
}
]
function App () {
const [price, setPrice] = useState(1);
const renderCards = (cardDetails) => {
return (
cardDetails.map((c) => {
<Card cardData={c} setPrice={setPrice} />
})
)
};
return (
<>
{renderCards(cardDetails)}
</>
)
}