我搬到类的外部函数和由常量。现在的功能不起作用

问题描述 投票:0回答:1

我搬到了Counter类外的函数addONe。这样的功能addOne后不工作了,但在另一边,我不接受任何错误。我的问题是我做错了什么,该常量addOne不工作?

import React from 'react';

const addOne = () => {
        this.setState((prevState) => {
            return {
                count: prevState.count + 1
            }
        })
    }


export default class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.minusOne = this.minusOne.bind(this);
        this.reset = this.reset.bind(this);
        this.state = {
            count: 0
        }
    }


    // addOne() {
    //     this.setState((prevState) => {
    //         return {
    //             count: prevState.count + 1
    //         }
    //     })
    // }

    minusOne() {
        this.setState((prevState) => {
            return {
                count: prevState.count - 1
            }
        })
    }

    reset() {
        this.setState(() => {
            return {
               count: 0// count: 0
            }
        })
    }

    render() {
        return (
            <div>
                <h1>Count: {this.state.count}</h1>
                <button onClick={this.addOne}>+1</button>
                <button onClick={this.minusOne}>-1</button>
                <button onClick={this.reset}>reset</button>
            </div>
        )
    } 
}
reactjs class const setstate
1个回答
4
投票

它不能正常工作。

你是你的函数内部访问this.setState,但你没有任何setState方法在你的范围,因为它是正确的React.Component类的。

真正的问题是:你为什么要搬出类addOne功能?

Edit due to your comment

如果你正在学习,你需要一个更技术性的解释:)

首先,你需要访问setState类的React.Component方法之外呢,在你addOne功能。我们需要在this.setState存在绑定到该函数的上下文。还有什么比组件本身的背景下更好?

让我们更新的渲染方法将下面一行:

<button onClick={this.addOne}>+1</button>

这一个:

<button onClick={addOne.bind(this)}>+1</button>

这里发生了什么事?功能addOne被接收外部上下文(在这种情况下,this)。这方面,将用作函数内this关键字。技术上,结合另一种情况下创建一个新的有界函数,但是这是我们这里不关心另外一个问题。

如果您尝试这个小编辑它仍然是行不通的。

那是因为你作为一个lambda函数表达式声明addOne。在ES6,lambda函数不能绑定了其他上下文。

事实上,如果你从一个lambda函数表达式将您addOne到函数声明,如下所示:

function addOne() {
  this.setState(prevState => ({
    count: prevState.count + 1
  }));
}

...你会看到,增加正常工作:)

希望它可以帮助您了解是怎么回事。

保持ES6语法

现在,使用ES6拉姆达函数表达式不是impossibile,它只是移动了同样的问题有点人行道。我们不能绑定另一个方面,但我们可以保持关闭它调用驻留或具有正确的上下文中的方法。

例如,我们可以改变addOne函数表达式为高阶函数,即采取setState并返回你所需要的点击处理程序:

const addOne = setState => () =>
  setState(prevState => ({
    count: prevState.count + 1
  }))

现在,在渲染方法,我们可能会认为这样使用它:

<button onClick={addOne(this.setState)}>+1</button>

传递setState作为函数参照。

现在的微妙的问题是,setState函数内addOne没有它的原始环境的约束!

我们可以解决这个问题:

<button onClick={addOne(this.setState.bind(this))}>+1</button>

Edit due to your last comment

这些语法的行为如出一辙:

const addOne = setState => () =>
  setState(prevState => ({
    count: prevState.count + 1
  }))

const addOne = setState => () =>
  setState(prevState => {
    return { count: prevState.count + 1 }
  })

他们的工作是相同的,方式是因为拉姆达函数表达式,如果你有一个单独的语句作为函数体,该语句的评估结果自动返回。

这意味着,lambda函数可以短为:

const five = () => 5
// five() returns immediate value 5

说,当你有:

prevState => {
  return { count: prevState.count + 1 }
}

要创建一个身体与返回平原对象的单个声明。

你看到的相似?您正在做同样的事情:有一个返回的东西单个语句。

可以拿出你记住的第一件事可能是重写它省略return关键字,如:

prevState => {
  count: prevState.count + 1
}

但是,这是行不通的。它会给你一个语法错误,由于是不应该存在的冒号。它不应该出现,因为如果一个lambda函数表达式体被定义为块(包装与{}一切),它应该有一个以上的声明和,也许,一return关键字。

为了使其工作,我们需要把普通对象定义为一个单独的语句,而我们做到这一点的包成圆形的括号,如:

prevState => ({
  count: prevState.count + 1
})

再次,希望它有助于:)

© www.soinside.com 2019 - 2024. All rights reserved.