Skip to content

是否考虑新增一个useExpect #2175

Closed
@YinDongFang

Description

@YinDongFang

开发表单时多个表单值存在依赖关系时需要通过useEffect更新表单值:

function CreateForm() {
  const form = useFormInstance();
  const formValueOfA = useWatch("a"); // initialValue: a
  const formValueOfB = useWatch("b"); // initialValue: b

  useEffect(() => {
    if (a === "newValueA") {
       form.setFieldValue("b", "newValueB");
    }
  }, [formValueOfA]);

  useEffect(() => {
    console.log([formValueOfA, formValueOfB]);
    // [a, b]
    // [newValueA, b]    非预期的中间状态
    // [newValueA, newValueB]
  }, [formValueOfA, formValueOfB]);
}

useEffect更新依赖状态的问题在于当前render阶段获取的仍是旧值,需要在下次render才能获取到新值,这样就存在非预期的中间状态

这种场景不只在于同步表单状态,也可能是在useEffect中更新其他state

个人感觉这种场景也算是比较通用场景,可以通过一个hooks在当前render阶段获取预期值(仍然在useEffect阶段更新)

/**
 * 根据依赖项和shouldUpdate判定条件返回状态的预期值
 * 场景:主要用于useEffect更新form表单状态时,为了在当前render阶段获取到预期的表单值
 * @param shouldUpdate 判定状态是否需要更新(依赖项未变化时不执行)
 * @param next 返回预期值(需要更新的情况下返回)
 * @param current 当前值(不需要更新的情况下返回)
 * @param update 更新操作,一般是更新表单内容(需要更新时执行)
 * @param deps 依赖项
 */
export function useExpect(
  shouldUpdate: (previousDeps: DependencyList, newDeps: DependencyList) => boolean,
  next: () => void,
  current: () => any,
  update: (v: any) => void,
  deps: DependencyList,
) {
  const depsRef = useRef<DependencyList>();
  const previousDeps = depsRef.current;
  const depsChanged = deps?.length !== previousDeps?.length || deps?.some((dep, i) => dep !== previousDeps?.[i]);
  depsRef.current = deps;
  const isShouldUpdate = depsChanged ? shouldUpdate(previousDeps, deps) : false;
  const expectedValue = isShouldUpdate ? next() : current();
  useEffect(() => {
    if (isShouldUpdate) update(expectedValue);
  });
  return expectedValue;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions