如何让 React 中的 onClick 处理具有多个兄弟姐妹的单个元素?
Posted
技术标签:
【中文标题】如何让 React 中的 onClick 处理具有多个兄弟姐妹的单个元素?【英文标题】:How to get onClick in React to work on a single element with multiple siblings? 【发布时间】:2020-11-22 09:09:02 【问题描述】:我是 React 新手,在尝试触发 onClick 事件时遇到问题。我有事件工作,当它被点击时,div 出现并重新出现。问题是,如果我按下特定项目的按钮,所有的 div 都会出现,而不是我刚刚单击按钮的 div。如何使我单击的按钮仅在该特定元素上触发。
这是我的代码:
类 App 扩展 React.Component
constructor(props)
super(props)
this.state =
userInput: '',
getRecipe: [],
ingredients: "none"
handleChange = (e) =>
this.setState(
userInput: e.target.value
)
handleSubmit = (e) =>
e.preventDefault()
const getData = () =>
fetch(`https://api.edamam.com/search?q=$this.state.userInput&app_id=$APP_ID&app_key=$APP_KEY&from=0&to=18`)
.then(res =>
return res.json()
).then(data =>
this.setState(
getRecipe: data.hits
)
)
getData()
// this is where the button logic comes in
getIngredients = (e) =>
e.preventDefault()
if (this.state.ingredients === 'none')
this.setState(
ingredients: "block"
)
else
this.setState(
ingredients: "none"
)
render()
return (
<div className="recipes">
<Nav changed=this.handleChange submit=this.handleSubmit />
<Content
userInput=this.state.userInput
recipe=this.state.getRecipe
getIngredients=this.getIngredients
ingredients=this.state.ingredients />
</div>
)
const Content = ( userInput, recipe, getIngredients, ingredients ) =>
return (
<div>
<h2 className="userinputtitle"> userInput </h2>
<div className="containrecipes">
recipe.map(rec =>
return (
<div key=rec.recipe.label className="getrecipes">
<h1 className="recipetitle" key=rec.recipe.label>rec.recipe.label.toUpperCase()</h1>
<img src=rec.recipe.image></img>
<h4 className="health"> Health Labels: rec.recipe.healthLabels.join(', ')</h4>
<h4 > Diet Label: rec.recipe.dietLabels</h4>
<h4 > Calories: Math.floor(rec.recipe.calories)</h4>
<h4 className="cautions"> Cautions: rec.recipe.cautions</h4>
<div>
<h4>rec.recipe.digest[0].label + ":" + " " + Math.floor(rec.recipe.digest[0].total) + "g"</h4>
<h4>rec.recipe.digest[1].label + ":" + " " + Math.floor(rec.recipe.digest[1].total) + "g"</h4>
<h4>rec.recipe.digest[2].label + ":" + " " + Math.floor(rec.recipe.digest[2].total) + "g"</h4>
</div>
// the button is clicked here, yet all div fire at the same time
<button onClick=getIngredients className="getingredients">Ingredients</button>
rec.recipe.ingredients.map(i =>
return (
<div style= display: ingredients className="containingredients">
< ul className="ingredients">
<li className="ingredient">i.text</li>
</ul>
</div>
)
)
</div>
)
)
</div>
</div>
)
【问题讨论】:
要么为映射的数据添加一个属性,要么保留一个单独的数据结构来为要切换的特定元素保持“切换”状态。使用元素 ID 切换值。更新getIngredients
回调以使用此唯一 ID。如果您遇到困难或实施问题,请尝试此操作并更新问题。
@DrewReese 我无法理解通过向映射数据添加属性的含义。
我的意思是你可以扩充你的数据并为每个元素添加一个属性来切换。我在下面回答时只使用了一个额外的数据结构。
【参考方案1】:
更新 getIngredients
以使用配方 ID 并将其保存在状态中。
切换单一配方成分
this.state =
userInput: '',
getRecipe: [],
ingredientsId: null
...
getIngredients = recipeId => e =>
e.preventDefault();
this.setState(prevState => (
ingredientsId: prevState.ingredientsId ? null : recipeId,
));
...
<Content
userInput=this.state.userInput
recipe=this.state.getRecipe
getIngredients=this.getIngredients
ingredientsId=this.state.ingredientsId // <-- pass id
/>
有条件地设置Content
中的显示样式。
const Content = ( userInput, recipe, getIngredients, ingredientsId ) =>
...
<button
onClick=getIngredients(recipe.id) // <-- pass id
className="getingredients"
>
Ingredients
</button>
<div
style=
// set display style
display: ingredientsId === recipe.id ? "block" : "none"
className="containingredients"
>
<ul className="ingredients">
<li className="ingredient">i.text</li>
</ul>
</div>
...
切换多个配方成分
同上,稍作改动
状态是地图
this.state =
userInput: '',
getRecipe: [],
ingredientsId: ,
在处理程序中切换 id
getIngredients = recipeId => e =>
e.preventDefault();
this.setState(prevState => (
ingredientsId:
...prevState.ingredientsId,
[recipeId]: !prevState.ingredientsId[recipeId]
,
));
在传递的地图中查找recipeId
style=
// set display style
display: ingredientsId[recipe.id] ? "block" : "none"
【讨论】:
@Alanaj "state",或者在本例中命名为prevState
,是 API 的一部分 setState
更新程序函数的第一个参数。 reactjs.org/docs/react-component.html#setstate 通常称为功能状态更新。
@Alanaj 如果这有助于解决您的问题,那么请接受回答并投票,干杯。
@Alanaj 并不是真的一个人变成另一个人,而是有点相反。在这种情况下,它假设recipe
对象具有id
属性,并且此ID 是传递给回调getIngredients
并保存到名为recipeId
的局部变量。
@Alanaj 很抱歉造成混淆。是的,任何在您的数据集中唯一的配方标识符。通常它是一个 id 字段,但它实际上可以是任何东西,它只需要是唯一的。
@Alanaj 这是一个curried 函数,即特别是一个接受 id 并返回一个接受事件对象的函数的函数。这就是写onClick=getIngredients(id)
和onClick=e => getIngredients(e, id)
的区别。以上是关于如何让 React 中的 onClick 处理具有多个兄弟姐妹的单个元素?的主要内容,如果未能解决你的问题,请参考以下文章
匿名函数如何在 React 组件中的 onClick 中工作?
如何在 React 中检测图像地图中的区域标签 onClick