首页 > 语言 > JavaScript > 正文

React 使用Hooks简化受控组件的状态绑定

2024-05-06 15:41:36
字体:
来源:转载
供稿:网友

开始之前

阅读本文需要对以下几项有一定了解

ECMAScript 6

文章中大量用到了 ES6 语法,比如解构赋值和函数参数默认值、剩余参数、展开语法、箭头函数等。

Hooks

React 在 16.8 版本中推出了 Hooks,它允许你在“函数组件”中使用“类组件”的一些特性。

React 本身提供了一些 Hooks,比如 useState、useReducer 等。通过在一个以“use”作为命名起始的函数中调用这些 Hooks,就得到了一个 custom Hook(自定义 Hook)。

Custom Hooks 允许我们把任何逻辑封装到其中,以便于复用足够小的组件逻辑。

Controlled Components

当我们把像 <input> <textarea> 和 <select> 这样的 HTML 元素本身的状态交给 React state 去管理,我们就得到了一个“受控组件”。

styled-components

一个与 React 契合良好的 CSS in JS 库。它允许你使用 JS 编写样式,并编译成纯 CSS 文件。
下面代码中所有的样式都是使用它编写的。如果对代码中样式的实现不是很感兴趣的话, 这个可以跳过。

代码实现

Input 组件

首先我们需要实现一个 Input 组件,我们将在该组件的基础上进行输入、校验并提示。

Input.js

import React from 'react';import PropTypes from 'prop-types';import styled from 'styled-components';const Wrap = styled.div({ display: 'flex', flexDirection: 'column', label: { display: 'flex', alignItems: 'center' }, input: {  marginLeft: 8, }, p: {  color: 'red', },});function Input({ label, type, helperText, error, ...otherProps }) { return (  <Wrap>   <label>    {label}:    <input {...otherProps} type={type} />   </label>   {error && <p>{helperText}</p>}  </Wrap> );}Input.propTypes = { label: PropTypes.string, type: PropTypes.string, helperText: PropTypes.string, error: PropTypes.bool,};export default Input;

该组件主要接收以下几个 props:

label label 标签的文本 type 赋值给原生 input 标签的 type 属性 error 数据类型为 Boolean,如果为 true 则表示当前表单域有错误,即验证不通过 helperText 当前表单域验证不通过时,显示在表单域下方的提示文字 otherProps props 中除了上述四个以外的其他属性,全部赋值给原生 input 标签

Custom Hook

有了 UI 组件之后,就可以开始实现我们的自定义 Hook 了。

useInput.js

import { useState } from 'react';export default function useInput({ initValue = '', helperText = '', validator = () => true, validateTriggers = ['onChange'],} = {}) { // 保存用户输入的值,使用 initValue 作为初始值 const [value, setValue] = useState(initValue); // Boolean 类型,表示当前表单项的验证状态 const [error, setError] = useState(false); function onChange(e) {  const { value } = e.target;  setValue(value);  // 根据 validateTriggers 的选项,决定是否要在 onChange 里进行校验  if (validateTriggers.includes('onChange')) {   setError(!validator(value));  } } /**  * 根据 validateTriggers 生成相应的事件处理器  */ function createEventHandlers() {  const eventHandlers = {};  validateTriggers.forEach(item => {   // 生成相应的事件处理器,并在其中做输入校验。   eventHandlers[item] = e => {    const { value } = e.target;    setError(!validator(value));   };  });  return eventHandlers; } const eventHandlers = createEventHandlers(); return {  value,  helperText,  error,  ...eventHandlers,  onChange, };}            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选