每天学点React - 高阶函数和函数柯里化

209 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

高阶函数

定义: 如果一个函数符合下面两个规范中的任何一个,那么该函数就是高阶函数

  • 若函数A,接收的参数是一个函数,那么A就是高阶函数
  • 若函数A,调用的返回值仍然是一个函数,那么A就是高阶函数

在上一篇《每天学点React - 受控组件与非受控组件》中,我们两个输入框分别实现了两个监听事件,在属性少的时候还好,如果当前页面为注册页面,有几十个属性项,那么我们会多很多重复的代码片段,这种编码方式是非常不妥的,那么,有没有什么方式可以解决该问题呢?

我有一位同事甲,他会想到,那么我来给它封装一下,把输入框对应的字段给它传递进去,哗哗哗的很快把代码敲出来了:

<script type="text/babel">
    class LoginInfo extends React.Component {

        // 初始化状态
        state = {
            username: '',
            password: ''
        }

        handlerSubmit = (event) => {
            // 阻止表单提交
            event.preventDefault()
            const {username, password} = this.state
            alert('用户名:' + username + `\n` + '密码:' + password)
        }

        // 更新state
        saveFormData = (dataKey) => {
            consolo.log(dataKey)
        }

        render() {
            return (
                <form action="http://www.baidu.com" onSubmit={this.handlerSubmit}>
                    用户名:<input onChange={this.saveFormData('username')} type="text" name="username" />
                    密码:<input onChange={this.saveFormData('password')} type="password" name="password" />
                    <button>登陆</button>
                </form>
            )
        }
    }

    ReactDOM.render(<LoginInfo />, document.getElementById("test"))
</script>

结果一看,好家伙,直接报错了

image.png

React的事件中,如果我们不加小括号,例如:

<input onChange={this.saveFormData} type="text" name="username" />

它是将saveFormData这个函数交给了onChange事件,而我们加上小括号的话,它是将saveFormData函数的返回值交给onChange事件作为回调,而在这个函数中,我们并没有返回值,获取到的就是undefined。那么,该问题又该如何解决呢?

很简单,我们将saveFormData函数的返回值交给onChange即可,例如:

<script type="text/babel">
    class LoginInfo extends React.Component {

        // 初始化状态
        state = {
            username: '',
            password: ''
        }

        handlerSubmit = (event) => {
            // 阻止表单提交
            event.preventDefault()
            const {username, password} = this.state
            alert('用户名:' + username + `\n` + '密码:' + password)
        }

        // 更新state
        saveFormData = (dataKey) => {
            return () => {
                console.log(this)
            }
        }

        render() {
            return (
                <form action="http://www.baidu.com" onSubmit={this.handlerSubmit}>
                    用户名:<input onChange={this.saveFormData('username')} type="text" name="username" />
                    密码:<input onChange={this.saveFormData('password')} type="password" name="password" />
                    <button>登陆</button>
                </form>
            )
        }
    }

    ReactDOM.render(<LoginInfo />, document.getElementById("test"))
</script>

可以看到,现在onChange事件可以正常触发了 image.png

又可以正常触发onChange事件了,同事甲:你走开,让我来!

<script type="text/babel">
    class LoginInfo extends React.Component {

        // 初始化状态
        state = {
            username: '',
            password: ''
        }

        handlerSubmit = (event) => {
            // 阻止表单提交
            event.preventDefault()
            const {username, password} = this.state
            alert('用户名:' + username + `\n` + '密码:' + password)
        }

        // 更新state
        saveFormData = (dataKey) => {
            return (event) => {
                this.setState({dataKey: event.target.value})
            }
        }

        render() {
            return (
                <form action="http://www.baidu.com" onSubmit={this.handlerSubmit}>
                    用户名:<input onChange={this.saveFormData('username')} type="text" name="username" />
                    密码:<input onChange={this.saveFormData('password')} type="password" name="password" />
                    <button>登陆</button>
                </form>
            )
        }
    }

    ReactDOM.render(<LoginInfo />, document.getElementById("test"))
</script>

一看结果,usernamepassword没啥变化,还多了一个dataKey属性出来了。

image.png

同事写习惯了,都忘记了对象的属性需要通过 中括号 来获取了,让我们来改造一下吧:

this.setState({[dataKey]: event.target.value})

setState()中的dataKey加上中括号就可以了,效果如下: image.png

函数柯里化

定义: 通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。

简单案例演示:

let demo = function (a){
    return (b) => {
        return (c) => {
            return a + b + c
        }
    }
}

image.png

saveFormData = (dataKey) => {
    return (event) => {
        this.setState({[dataKey]: event.target.value})
    }
}