UNPKG

@schema-render/core-react

Version:

Through a set of simple JSON Schema, efficiently build a set of forms.

81 lines (80 loc) 3.19 kB
import { useRef } from "react"; import { hasOwnProperty } from "../utils/base"; import { isFunction } from "../utils/checking"; import { stringifyPath } from "../utils/misc"; import { set } from "../utils/tinyLodash"; import useForceUpdate from "./useForceUpdate"; import useMemoizedFn from "./useMemoizedFn"; import useUnmountedRef from "./useUnmountedRef"; /** * 表单 value 受控与非受控模式支持 * 需要考虑【多渲染器内部 onChange 初始化值】场景,参考 952 调试文档 * @param props 内核参数 */ export default function useCoreValue(props) { const valueRef = useRef(props.defaultValue ?? {}); const isUnmountedRef = useUnmountedRef(); const { forceUpdate } = useForceUpdate(); // 是否受控模式,存在 value 字段即为受控模式 const isControlled = hasOwnProperty(props, 'value'); if (isControlled) { valueRef.current = props.value ?? {}; } // 处理回调事件 const handleChange = useMemoizedFn((nextValue, event)=>{ // 实例没有卸载时才可触发 “onChange” 事件 if (!isUnmountedRef.current) { var _props_watch, // 单个表单项 change 事件 _props_onItemChange, // 整个表单数据的 change 事件 _props_onChange; const sPath = stringifyPath(event.path); const eventInfo = { ...event, sPath }; const matchedWatch = (_props_watch = props.watch) === null || _props_watch === void 0 ? void 0 : _props_watch[sPath]; // watch 监听模式 if (isFunction(matchedWatch)) { matchedWatch(nextValue, eventInfo); } /** * React 18 多个子渲染器 useEffect 同时触发 onChange * 渲染流程不会通过应用层父组件重渲染来先更新 valueRef 的值 * 故这里需要内部更新赋值 */ valueRef.current = nextValue; // 非受控模式下内部更新,受控模式下由应用层父组件触发更新 if (!isControlled) { forceUpdate(); } (_props_onItemChange = props.onItemChange) === null || _props_onItemChange === void 0 ? void 0 : _props_onItemChange.call(props, eventInfo); (_props_onChange = props.onChange) === null || _props_onChange === void 0 ? void 0 : _props_onChange.call(props, nextValue, eventInfo); } }); // 使 onChange 不可变 const onChange = useMemoizedFn((event)=>{ const nextValue = set({ ...valueRef.current }, event.path, event.value); handleChange(nextValue, event); }); // 获取表单数据 const getValue = useMemoizedFn(()=>valueRef.current); // 设置表单数据 const setValue = useMemoizedFn((nextValue)=>{ handleChange(nextValue, { path: [], value: undefined }); }); // 重置表单数据 const resetValue = useMemoizedFn(()=>{ setValue({}); }); return { value: valueRef.current, valueRef, onChange, getValue, setValue, resetValue }; }