当前位置: 首页 > 知识库问答 >
问题:

如何让onClick-in-React处理具有多个同级的单个元素?

方鸿振
2023-03-14

我是个新手,在尝试触发onClick事件时遇到了问题。我让事件工作,当它被点击时,div出现并重新出现。问题是,如果我按下某个特定项目的按钮,所有div都会出现,而不是我刚才单击按钮的div。如何使我单击的按钮仅在该特定元素上启动。

这是我的代码:

类应用程序扩展了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>

    )
}

共有1个答案

慕弘深
2023-03-14

更新getComponents以同时使用配方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"
}}
 类似资料:
  • 问题内容: 我希望能够设置各个片段视图的setText和getText。就像现在一样,当我使用Framgent的TextView的setText时,它会在所有片段中更改该View的文本。 我一直在尝试着四处移动,但是到现在为止,这是我的代码: 片段类 活动课 framgent.xml很简单;只是一个TextView。 问题答案: 使用名为tag的参数将片段添加到堆栈中。在您的情况下,您已将片段添加

  • 我在视图布局中使用了三个EditText小部件,用于三个不同的过滤器。如果我输入其中一条,另一条文本不应该是空白的吗? 下面是我的片段: GenericTextWatcher方法: 当我运行这个程序并输入EditText时,logcat看起来是这样的: 03-03 15:25:39.616 25952-25952/com.xyz.abcI/art:显式并发标记扫描GC释放23671(1194KB)

  • 我有一个有两个阶段的Dockerfile;第一阶段从源代码构建一个react应用程序,第二阶段复制构建并添加一个NGINX服务器: 我也在使用gitlab-ci,我希望有多个阶段:构建、测试和部署。但是我不知道如何将构建和测试阶段分开,因为我使用的是多阶段的DockerFile。问题是所有的JS测试(对于React)都需要在“Yarn build”执行之前运行,并且build被复制到seconds

  • 问题内容: 我有一个React应用,其中有许多导入相同模块的组件。webpack是否为每个请求它的文件导入每个模块一次,从而导致重复的代码(在这种情况下,每个模块仅对两个组件导入两次)?我正在考虑重新编写组件,以便子组件不需要使用React模块,但是也许我正在解决一个不存在的问题。我想避免同一反应模块的多次导入,如果它导致重复的代码。 组件1 组件2导入相同的3个模块。 问题答案: 不能,webp

  • 这是我的结果html页面: 这些结果与我的表单绑定如下: 我遇到的问题是,当返回结果页面时,无论有多少条条目,它都只显示第一条。为了显示所有结果,我需要做什么?