代码之家  ›  专栏  ›  技术社区  ›  kojow7

通过三个级别的组件传递函数(即从孙子组件调用函数)

  •  1
  • kojow7  · 技术社区  · 6 年前

    我想从子组件或孙子组件传递一个项目ID,但无法确定如何传递。我看过的其他示例显示了如何使用arrow函数来实现这一点,但是无论出于什么原因,我的函数都不会被调用。

    我有以下内容 Parent.js :

    chosenItem(id){
        console.log("CHOSEN ITEM SELECTED")
        this.setState({
            chosen_item: id
        })
    }
    

    在parent.js呈现函数中:

    <Child objects={objects} chosenItem={() => this.chosenItem()} />
    

    然后在我的 Child.js 我有:

    items = this.props.objects.items.map(item => {
        return (
            <ClickableTextComponent
                key={item.id}
                text={item.label}
                onClick={item =>this.props.chosenItem(item.id)}
             />
         )
     })
    

    在my child.js呈现函数中,我有:

    {items}
    

    我也不确定实际的click事件应该放在child.js或clickabletextcomponent中。还是真的很重要?目前我已经将它放在child.js组件中,如上图所示。

    我做错什么了?如何修改代码以便调用函数?我读过一些关于currying的文章,以防止函数被多次重新创建。在这种情况下这是必要的吗?如果是这样,我应该在哪里以及如何实现它。在我的父组件或子组件中?

    更新

    我以前试图让onclick从child.js开始工作,但是由于它需要附加到一个div,所以我把它移到了clickabletextcomponent(孙子组件)。

    一个问题 ClickableTextComponent 我希望能够设置组件被单击时的状态,以便我可以将组件转换为不同的颜色。因此,我需要使用一个函数来调用chosenitem函数。下面是我在“clickabletextcomponent.js”中的内容:

    handleClick(){
        this.setState({
            text_state: "clicked"
        })
        this.props.chosenItem()
    }
    

    在渲染中,我有:

    <div
        onClick={this.handleClick.bind(this)}
        onMouseOver={this.changeTextState.bind(this, "hover")}
        onMouseOut={this.changeTextState.bind(this, "default")}
    >{this.props.text}</div>
    

    新错误

    基于上述变化,我现在 this.props.chosenItem is not a function .然而,我不明白它为什么会给我这个错误。我显示时可以看到函数名 this.props 到控制台。我做错什么了?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Tolsee    6 年前

    他给出的答案是正确的。但这个解决方案有一个问题。

    <Child objects={objects} chosenItem={(x) => this.chosenItem(x)} />
    

    当你这样做的时候,每次你的父母都会重新归位。它将创建函数的新实例。而且,您的子组件也会重新发送,因为它看到 props 改变。

    最佳解决方案是:

    <Child objects={objects} chosenItem={this.chosenItem} />
    

    更新:

    现在,这似乎是有道理的。

    问题再次出现在 ClickableTextComponent .

    这是最新消息 可单击文本组件 它起作用。

    https://codesandbox.io/s/73x6mnr8k0

    主要问题:

    items = this.props.objects.items.map(item => {
        return (
            <ClickableTextComponent
                key={item.id}
                text={item.label}
                onClick={item =>this.props.chosenItem(item.id)}
             />
         )
     })
    
    //
    // Here you made a function (item) => this.props.choseItem(item.id)
    // That means when you call that function you should call like this
    // i.e. passing parameter needed for the function
    // 
    
    handleClick(){
        this.setState({
            text_state: "clicked"
        })
        this.props.chosenItem(item)
    }
    
    //
    // But do you do not have the item in the children
    // Parent should be changed as below
    //
    
    items = this.props.objects.items.map(item => {
        return (
            <ClickableTextComponent
                key={item.id}
                text={item.label}
                onClick={() =>this.props.chosenItem(item.id)}
             />
         )
     })
    
    //
    // Now you made a fuction () => this.props.chosenItem(item.id)
    // The main difference being you are not taking a item as parameter
    // item will be taken from outer scope that means, item from map
    //
    
    // 
    // Another solution can be
    // 
    
    items = this.props.objects.items.map(item => {
        return (
            <ClickableTextComponent
                key={item.id}
                id={item.id}
                text={item.label}
                onClick={this.props.chosenItem}
             />
         )
     })
    
    // And in ClickableTextComponent
    
    handleClick(){
        this.setState({
            text_state: "clicked"
        })
        this.props.chosenItem(this.props.id)
    }
    
    
        2
  •  1
  •   Kevin He    6 年前

    您可以这样做:

    <Child objects={objects} chosenItem={(x) => this.chosenItem(x)} />
    

    注意 chosenItem 是一个函数,然后每当用 item.id ,调用函数 this.chosenItem 在父元素。