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.
CodePudding user response:
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);
};