Home > Enterprise >  ReactJS - Can i save specific rendered mapped data, to a variable?
ReactJS - Can i save specific rendered mapped data, to a variable?

Time:09-22

I have data mapped in a component like this:

import React from "react";
import { useState } from "react";
import { useEffect } from "react";
import { get } from "lodash";

const Products = ({ data }) => {
return (
  data.map((item, index) = > (
  <div id={index}>
    <img src={item.img} /> <br />
    {item.name} <br />
    {get(moreData, `[${item.name.toLowerCase()}].info[0]`)}
    {get(moreData, `[${item.name.toLowerCase()}].info[1]`)}
    {get(moreData, `[${item.name.toLowerCase()}].info[2]`)}
  </div>

I want to be able to store this data:

    {item.name} 
    {get(moreData, `[${item.name.toLowerCase()}].info[0]`)} 
    {get(moreData, `[${item.name.toLowerCase()}].info[1]`)}
    {get(moreData, `[${item.name.toLowerCase()}].info[2]`)}

in a string, like string = {item.name},{moreData.item.name.toLowerCase().info[0]},...//etc

However you cannot declare variables inside of a component (as far as i know, still new to this).

I've tried .concat() - after each line and .push() with array instead of string:

    {item.name} <br /> 
      {dataString.concat(item.name)}
      {dataArr.push(item.name)}
    {get(moreData, `[${item.name.toLowerCase()}].info[0]`)}
    {get(moreData, `[${item.name.toLowerCase()}].info[1]`)}
    {get(moreData, `[${item.name.toLowerCase()}].info[2]`)}

I was going to use DOM, but i've been told it's bad practice to use DOM in react.

I've also tried using state in the same way:

const [dataString, setDataString] = useState(""); ...

      {item.name}
      {setDataString((dataString  = item.name))}

But nothing seems to work as intended for me, and i'm out of ideas.

Edit:

I want to be able to copy the 'string/text' to clipboard eventually. So it can be imported to another site. Their required format is Item1, item1-info1, item1-info2, item1-info3, item2, item2-info1, item2-info2, item2-info3...etc

CodePudding user response:

here is an example of how you can use the data object outside of the mapped objects. also an example how to convert the data to an string in the format required. because I don't know the structure of the data object of yours I just created an one, take this code and change it to the data structure

      const data = [
        {
          name: "name1",
          info1: "info1-1",
          info2: "info1-2",
          info3: "info1-3",
        },
        {
          name: "name2",
          info1: "info2-1",
          info2: "info2-2",
          info3: "info2-3",
        },
        {
          name: "name3",
          info1: "info3-1",
          info2: "info3-2",
          info3: "info3-3",
        },
      ];

change this function to one that fits your needs.

  const getStringOfData = (data) => {
    let stringArray = [];
    data.map((item) => {
      stringArray.push(item.name);
      stringArray.push(item.info1);
      stringArray.push(item.info2);
      stringArray.push(item.info3);
    });
    let stringResult = stringArray.join(",");
    return stringResult;
  };

  useEffect(() => {
    console.log("onMounte with useEffect");
    let stringResult = getStringOfData(data)
    console.log(stringResult);

  }, []);

you can also call this function on onClick function depend in your requirement , the data object is available almost everywhere in your component

CodePudding user response:

Continuing our discussion from the comments, it looks like there are two different things you are trying to do here:

  1. display the UI to the user in a certain way
  2. to be able to copy the information in a specific stringified format

I would advice to split these two behaviors, because they are totally unrelated to each other in terms of logic.

Start by aligning the information in your components how you need it.

const Product = ({ item, index }) => {

   // do whatever you need to do with the information 
   // to display it correctly
   const identifier = name.toLowerCase()
   const infos = (moreData[identifier] && moreData[identifier].info) || {}
   
   return (
     <div>
       { info[0] && <p> info[0] </p>}
       { info[1] && <p> info[1] </p>}
       { info[1] && <p> info[2] </p>}
     </div>
   )
}


const Products = ({ data }) => {

 const onClick = useCallback(
   async () => {
     // parse data and copy it using a separate
     // util method.
     const dataToString = /* actual implementation of the formatting to a string representation */ 
     copyTextToClipBoard(dataToString)
   },
   [data]
 )
return (
  <div>
   <button onClick={onClick} />
   <div>
    data.map((item, index) => (
      <Product item={item} index={index} key={item.id} />
    ))
   </div>
  </div>
)
};

Now this would be your UI, the copyToClipboard method, is a bit of a hack, and looks like so:


const copyTextToClipBoard = (text) => {
  const element = document.createElement('textarea');

  element.style = { display: 'none' }; // eslint-disable-line
  element.value = text;

  document.body.appendChild(element);
  element.select();
  document.execCommand('copy');
  document.body.removeChild(element);
};
  • Related