Javascript this.setState不是一个函数

Javascript this.setState不是一个函数,javascript,reactjs,Javascript,Reactjs,我知道对于这种情况有很多答案,包括使用bind或arrow函数,但我的情况有点不同。基本上,我想创建一个带有EventListener的div元素,该元素用我单击的特定子元素的索引值更新statesetIndex值。此过程的回调函数是onmodel 如果我对onModal使用箭头函数,则'this'关键字将被传输到类而不是单个元素,因此我将无法访问单个元素的索引 如果我使用正常函数(正如我在下面的代码中所演示的那样),那么this.setState会被传输到各个元素,我会得到setState错误

我知道对于这种情况有很多答案,包括使用bind或arrow函数,但我的情况有点不同。基本上,我想创建一个带有EventListener的div元素,该元素用我单击的特定子元素的索引值更新statesetIndex值。此过程的回调函数是onmodel

如果我对onModal使用箭头函数,则'this'关键字将被传输到类而不是单个元素,因此我将无法访问单个元素的索引

如果我使用正常函数(正如我在下面的代码中所演示的那样),那么this.setState会被传输到各个元素,我会得到setState错误

class AddRecipe extends Component{
  constructor() {
    super();
    this.state={
      name:[],
      setIndex:0,
    }
  }

  onLoad() {

    var recipe = document.querySelector(".recipe")

    const name = data.forEach((d,index) => {
      var recipecard = document.createElement("div")
      recipecard.setAttribute("class","recipecard")
      recipecard.setAttribute("key",index)
      recipe.setAttribute("key",0)
      var h1 = document.createElement("h1")
      h1.setAttribute("id","keyhold")
      h1.appendChild(document.createTextNode(data[index].name))
      console.log(h1);
      recipecard.appendChild(h1)
      recipecard.addEventListener("click",this.onModal)
      recipe.appendChild(recipecard)
    })
  }

  componentDidMount() {
    this.onLoad()
  }

  onModal() {
    var index = this.getAttribute("key")
    var recipe = document.querySelector(".recipe")
    recipe.setAttribute("key",index)
    var modal = document.getElementById('MyModal')
    var btn = document.getElementById('myBtn')
    var modal = document.getElementById('myModal');
    var btn = document.getElementById("myBtn");
    modal.style.display = "block";

    this.setState({setIndex:index}).bind(this)

  }

  onClose() {
    var modal = document.getElementById('myModal');
    var span = document.getElementsByClassName("close")[0]
    modal.style.display= "none"
  }

  render() {
    return (
      <div>
        <div id="myModal" class="modal">
          <div class="modal-content">
            <span onClick={this.onClose.bind(this)} class="close">&times;</span>
            <ModalWindow datas= {data} index={this.state.setIndex} />
          </div>
        </div>
        <div className ="recipe">
        </div>
      </div>
    );
  }
}

export default AddRecipe
类AddRecipe扩展组件{
构造函数(){
超级();
这个州={
姓名:[],
集合索引:0,
}
}
onLoad(){
var recipe=document.querySelector(“.recipe”)
const name=data.forEach((d,索引)=>{
var recipecard=document.createElement(“div”)
recipecard.setAttribute(“类”、“recipecard”)
recipecard.setAttribute(“键”,索引)
recipe.setAttribute(“键”,0)
var h1=document.createElement(“h1”)
h1.setAttribute(“id”、“keyhold”)
h1.appendChild(document.createTextNode(数据[index].name))
控制台日志(h1);
recipecard.appendChild(h1)
recipecard.addEventListener(“单击”,this.onModel)
recipe.appendChild(recipecard)
})
}
componentDidMount(){
this.onLoad()
}
onModal(){
var index=this.getAttribute(“键”)
var recipe=document.querySelector(“.recipe”)
recipe.setAttribute(“键”,索引)
var modal=document.getElementById('MyModal'))
var btn=document.getElementById('myBtn')
var modal=document.getElementById('myModal');
var btn=document.getElementById(“myBtn”);
modal.style.display=“块”;
this.setState({setIndex:index}).bind(this)
}
onClose(){
var modal=document.getElementById('myModal');
var span=document.getElementsByClassName(“关闭”)[0]
modal.style.display=“无”
}
render(){
返回(
&时代;
);
}
}
导出默认AddRecipe

可能错误在行
recipecard.addEventListener(“单击”,this.onModel)
您需要向
this.onModel
调用添加绑定


我认为没有必要在
setState
上使用
bind
方法,recipecard.addEventListener(“单击”,this.onModal.bind(this))onModal必须绑定 我不确定这是否会在没有约束力的情况下起作用

 componentDidMount() {
    this.onLoad()
 }
在构造函数中添加代码行

this.onLoad = this.onLoad.bind(this)

索引
参数传递给事件处理程序并进行相应处理

此外,由于只需要元素上下文来检索
索引
,因此可以使用函数currying将
索引
发送到
onmodel
方法。这样,您就不必再依赖元素的上下文了

如果React项目支持类实例方法的箭头函数,则可以尝试传递如下参数

class AddRecipe extends Component{
  ...
  onLoad() {
    var recipe = document.querySelector(".recipe")
    const name = data.forEach((d,index) => {
      ...
      recipecard.addEventListener("click",this.onModal(index))             
      recipe.appendChild(recipecard)
    })
  }

  onModal = (index) => (event) => {
    ...    
    this.setState({ setIndex:index })    
  }
  ...
}

export default AddRecipe

您甚至可以尝试在React文档中记录它的方式,以避免任何混淆

查看本文,了解向事件处理程序发送参数的多种方法


绑定将附加第一个参数作为调用绑定的函数的上下文(即“this”),并返回一个具有新上下文的新函数

this.setState({…})是一个函数调用,因此无法绑定任何this。 你需要这样的东西:

onLoad(){

  var recipe = document.querySelector(".recipe")
  const name = data.forEach((d,index) => {
    (...)
    // !!! bind this to onModal
    recipecard.addEventListener("click",this.onModal.bind(this))
    (...)
}) }
因此,如果将“this”绑定到onModal,那么在click事件上调用的函数将使用类的上下文,因此它可以调用类的setState

编辑

你也可以用南都岛答案的第二部分。
箭头函数自动具有创建它们的位置的上下文,因此具有onLoad的上下文,即类的上下文。

remove.bind(此)在this.setState之后,我认为没有必要在
setState
上使用
bind
方法,而且错误可能在
recipecard.addEventListener行(“单击”,this.onModel)
您需要向
this.onModal
调用添加绑定。其他用户可能会突出显示错误,但真正的错误是React不是为使用文档(document.createElement)而构建的和其他类似的东西。你必须使用呈现和状态来理解呈现的内容。你可以使用React-ref API来获取元素信息。在我看来,它就像你的onLoad()正在做大量的杂耍来避免使用refs,但是refs在React 16中的使用变得更加容易。如果我这样做,我将创建一个RecipeCard类,并使用refs将我的事件处理程序附加到该类。以下是文档(),如果您想了解有关实现此功能的更多信息,请告诉我。我100%支持@PaoloDell'Aguzzo,最好使用您需要的所有信息创建另一个组件,而不是直接操作DOM。我从未见过事件以这种方式处理,但您的方法给出了最好的答案。感谢绑定到集合状态是一个输入错误。绑定是否正确但是,让它引用AddRecipe类而不是配方卡?
onLoad(){

  var recipe = document.querySelector(".recipe")
  const name = data.forEach((d,index) => {
    (...)
    // !!! bind this to onModal
    recipecard.addEventListener("click",this.onModal.bind(this))
    (...)
}) }