React@16.x(14)context 举例 - Form 表单

目录

1,目标

上篇文章说到,context 上下文一般用于第3方组件库,因为使用场景是需要多个组件之间相互配合实现一整套的逻辑。(高内聚的思想)

所以利用上下文的特性简单封装一个表单,看看如何实现和使用。

在 element-ui 中 Form 表单组件之间的联动,也是一个思想。它使用的 发布订阅模式 来逐层传递数据。

2,实现

整体目录:

txt 复制代码
src/components/Form
-- index.js
-- context.js // 存放上下文数据。
-- FormInput.js
-- FormButton.js

2.1,index.js

js 复制代码
import React, { Component } from "react";
import PropTypes from "prop-types"; // 用于验证 props 类型
import { Provider } from "./context";
import FormInput from "./FormInput";
import FormButton from "./FormButton";

export default class Form extends Component {
    state = {
        formData: {},
        changeFormData: (name, value) => {
            this.setState({
                formData: {
                    ...this.state.formData,
                    [name]: value,
                },
            });
        },
        submit: () => {
            this.props.onSubmit?.(this.state.formData);
        },
    };

    static propTypes = {
        onSubmit: PropTypes.func,
    };

    render() {
        return <Provider value={this.state}>{this.props.children}</Provider>;
    }
}

// 赋值到 Form 组件上方便引用。
Form.Input = FormInput;
Form.Button = FormButton;

2.2,context.js

js 复制代码
import React from "react";

const ctx = React.createContext();
export const { Provider, Consumer } = ctx;
export default ctx;

2.2,Form.Input

注意 input.value 属性,因为 this.context.formData[this.props.name] 一开始是 undefined,所以得加一个默认值 '',否则 React 会认为是非受控组件而报错。

js 复制代码
import React, { Component } from "react";
import PropTypes from "prop-types";
import ctx from "./context";

export default class FormInput extends Component {
    static contextType = ctx;

    static defaultProps = {
        type: "text",
    };

    static propTypes = {
        type: PropTypes.string.isRequired,
        name: PropTypes.string.isRequired,
    };
    render() {
        return (
            <div>
                <input
                    type={this.props.type}
                    name={this.props.name}
                    value={this.context.formData[this.props.name] || ""}
                    onChange={(e) => {
                        this.context.changeFormData(this.props.name, e.target.value);
                    }}
                ></input>
            </div>
        );
    }
}

2.3,Form.Button

js 复制代码
import React from "react";
import { Consumer } from "./context.js";

export default function FormButton(props) {
    return (
        <Consumer>
            {(ctx) => {
                return <button onClick={() => ctx.submit()}>{props.children}</button>;
            }}
        </Consumer>
    );
}

3,使用

js 复制代码
import React, { Component } from "react";
import Form from "./components/Form/index";

export default class App extends Component {
    render() {
        return (
            <div>
                <Form
                    onSubmit={(formData) => {
                        console.log(formData);
                    }}
                >
                    <div>
                        <label>用户名</label>
                        <Form.Input name="id"></Form.Input>
                    </div>
                    <div>
                        <label>用户名</label>
                        <Form.Input name="pwd" type="password"></Form.Input>
                    </div>
                    <Form.Button>获取FormData</Form.Button>
                </Form>
            </div>
        );
    }
}

最终,点击按钮就能获取到 formData更新后的数据。


以上。

相关推荐
jktantan10 小时前
Vue keep-alive 切标签后滚动位置回顶?因为 onDeactivated 里读到的 scrollTop 是 0
前端·javascript·vue.js
总要学点什么10 小时前
第89篇:三维特效-螺旋圆效果——让螺旋臂卷起一圈圈外扩的涟漪
开发语言·javascript·ecmascript·webgl·cesium·空间分析·1024程序员节
前端精髓11 小时前
调用openrouter的免费API模型
java·前端·javascript
螺丝钉tina17 小时前
[Playwright] [02]常用命令与调试:Debug UI、Mode和 Trace Viewer
开发语言·javascript·测试工具·ui·自动化
开开心心就好18 小时前
竖式除法出题工具,整除余数混合模式
运维·服务器·前端·javascript·ocr·perl·1024程序员节
এ慕ོ冬℘゜19 小时前
JS 事件循环、宏任务微任务:单线程底层原理 + 执行顺序
开发语言·javascript·ecmascript
web打印社区19 小时前
Lodop排障总纲-常见报错一张表
开发语言·前端·javascript·chrome·websocket
程序员大阳19 小时前
副队长JavaScript教程(56)-DOM之表单操作
javascript·dom·表单操作
Dxy123931021620 小时前
JS AES加密详解
开发语言·javascript·ecmascript
FRing0320 小时前
JavaScript入门到精通三十三(异常处理、call方法、apply方法、bind方法、防抖、节流)
开发语言·前端·javascript