Home > Enterprise >  How to store a function name in JSON?
How to store a function name in JSON?

Time:07-30

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)}
    </>
  )
}
  • Related