2

fruit json value.

console.log(fruit)
[
    {
      content: "apple",
      information: [
        {
            calorie: "122"
        },
      ],
    },
    {
        content: "banana",
        information: [
          {
            calorie: "221"
          },
        ],
      },
    {
        content: "mango",
        information: [
          {
            calorie: "52"
          },
        ],
    },
];

Create a button by running the map function on the information on the fruit.

The dynamically created button is {value.calorie} first button 122 second button 221 third button 52 is created.

And the content also maps function to fruit and puts {fruit.content} as the argument value in the button.

And set useRef so that when the value.calorie button is clicked, the fruit content button is also clicked.

const Content = useRef(null);
const Calorie = useRef(null);


const onClickContent = (content) => {
  console.log(content);
};

const onClickCalorie = (calorie) => {
  Content.current.click();
  console.log(calorie);
};

return (
  <>

    fruit.map((Fields, index) => (
  <>
  <p>{Fields.content}</p>
  <button style={{"display": "none"}} ref={Content} onClick={() => onClickContent(Fields.content)}></button>
  </>

  {Fields.information.map((Value, key) => {
      return (
          <>
          <p>{Value.calorie}</p>
          <button onClick={() => onClickCalorie(Value.calorie)}>{Value.calorie}</button>
          </>
      )
  })}
  ))
  </>
)

The problem is that when you click the 122 displayed on the button, the content is also output to the console, apple should be output, but mango is output.
If you click the button with calorie 221, banan should be output, but mango is output to the console. This is said to be because of a single reference.
How can I solve the single reference function? I do not know.

skyboyer
  • 22,209
  • 7
  • 57
  • 64
minsu123
  • 419
  • 2
  • 8
  • Can't you remove the ref and instead make your calorie button or `onClickCalorie` call `onClickContent()` instead? – Nick Parsons Apr 18 '22 at 01:09
  • @NickParsons How can I get the Content if I remove useRef?, Isn't it possible to manually click the useRef with the button and receive it only in the form of adding the parameter value to the button ? – minsu123 Apr 18 '22 at 01:14
  • I guess what is the purpose of creating the `Content` ref? If it's just so that you can call `.click()` on it to trigger the `onClickContent()` then you don't need it, as you can call `onClickContent()` manually without needing to trigger a click on the `Content` button. When you call `onClickCalorie()`, you also have access to `Fields.content` so you can pass that through into your function to have access to the same data that `onClickContent()` needs when it gets called. – Nick Parsons Apr 18 '22 at 01:18
  • @NickParsons I set useRef.click so that if onClickCalorie is executed without clicking onClickContent , onClickContent is also executed. – minsu123 Apr 18 '22 at 01:23
  • @NickParsons I don't quite understand what you said. Can you explain with code? Shouldn't useRef be used? – minsu123 Apr 18 '22 at 01:28

1 Answers1

1

To me it looks like you can remove the ref, as all that it's currently being used for is to trigger a click event on your first (content) button when you click on your second (calorie) buttons. If that's the case, you can instead call onClickContent() manually inside of onClickCalorie(). First, you can update your onClickCalorie() to pass through the data that onClickContent() needs:

<button onClick={() => onClickCalorie(Value.calorie, Fields.content)}>{Value.calorie}</button>

Then, in your onClickCalorie(), update the parameters, and call onClickContent() manually to fire the same function you would trigger if you clicked your Content button:

const onClickCalorie = (calorie, content) => {
  onClickContent(content);
  // ... do stuff specific to clicking on the calorie button ...
  console.log(calorie);
};

This way, you don't need to use any refs, as you don't need to explicitly refer to any DOM elements.


If the only thing that your onClickCalorie() function does is call/trigger onClickContent(), then you can remove the onClickCalorie() function and call onClickContent() directly:

<button onClick={() => onClickContent(Fields.content)}>{Value.calorie}</button>

Otherwise, if you really need to use refs, you can follow this approach where you can create a ref for each of your buttons:

const contentBtns = useRef([]);

and then within a useEffect() update the array size if the fruit array changes:

useEffect(() => {
  contentBtns.current = contentBtns.current.slice(0, fruit.length);
}, [fruit]);

and then populate the array stored in contentBtns.current so that each index stores the button element:

<button 
  style={{"display": "none"}} 
  ref={el => contentBtns.current[index] = el} 
  onClick={() => onClickContent(Fields.content)}>
</button>

Now when you call onClickCalorie, you can refer to a specific button to click based on the index. You will need to pass through the index into your onClickCalorie() to have access to it:

const onClickCalorie = (calorie, index) => {
  contentBtns.current[index].click();
  console.log(calorie);
};
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
  • Do I have to concatenate the arrays if the other two arrays are objects of the other arrays? – minsu123 Apr 18 '22 at 01:40
  • @minsu123 Not too sure what the other two arrays are, but you should be able to use the `index`/`key` to relate the two without concatenating them if I understand correctly. – Nick Parsons Apr 18 '22 at 01:44
  • @minsu123 might be clearer if you share your data. But you can relate the two by using an index. You can pass anything you wish to `onClickCalorie()` – Nick Parsons Apr 18 '22 at 01:55