field-form icon indicating copy to clipboard operation
field-form copied to clipboard

listContext 造成useWatch 失效

Open closertb opened this issue 2 years ago • 0 comments

正常运行的版本: image

失效的版本 image

貌似是这个pr改动造成的:https://github.com/react-component/field-form/pull/582

看了源码,是由于ListContext 这个全局变量造成 isListField 被错误打标为true,造成:

// useForm.ts  getFieldsValue方法
if (!nameList && (entity as FieldEntity).isListField?.()) {
  return;
}

引起错误的代码为这里

  //  这里初始化时, 正常时拿到的是 null, 但那个错误包版本拿到的是 { f(getKeys) }
  const wrapperListContext = React.useContext(ListContext);

  const listContext = React.useMemo<ListContextProps>(
    () => ({
      getKey: (namePath: InternalNamePath) => {
        const len = prefixName.length;
        const pathName = namePath[len];
        return [keyManager.keys[pathName], namePath.slice(len + 1)];
      },
    }),
    [prefixName],
  );


    <ListContext.Provider value={listContext}>
      <FieldContext.Provider value={fieldContext}>
        <Field
          name={[]}
          shouldUpdate={shouldUpdate}
          rules={rules}
          validateTrigger={validateTrigger}
          initialValue={initialValue}
          isList
          isListField={isListField ?? !!wrapperListContext}
        >
<.....>

出错的场景就是 Form 嵌套,但formList 并没有嵌套,但共用了同一个 ListContext 伪代码如下

// ModalAdapter.tsx
export function ModalAdapter(props: {
  value?: any;
  onChange?: (value: any) => void;
}) {
    const [form] = Form.useForm();
     return (
     <Modal>
      <Form form={form}>
        <Form.Item lable="属性a">
          <Form.List name="attra">
            ....
          </Form.List>
        </Form.Item>
        <Form.Item lable="属性b">
          <Form.List name="attrb">
            ....
          </Form.List>
        </Form.Item>
      </Form>
     </Modal>);
}

// index.tsx

                  <Form.Item label="测试列表">
                    <Form.List
                      name="testList"
                    >
                      {(fields, { add, remove }) => (
                        <>
                          {fields.map(field => {
                            return (
                            <div key={field.key} className="setting-list-item">
                              {fields.length > 1 ? <CloseCircleFilled
                                style={{ color: '#CCCCCC' }}
                                onClick={() => {
                                  remove(field.name);
                                }}
                              /> : null}
                              <Form.Item
                                noStyle
                                name={[field.name, 'attr']}
                              >
                                <ModalAdapter  />
                              </Form.Item>
                            </div>
                          )
                          })}
                          {fields.length < 10 && <Form.Item>
                            <div onClick={add} className="setting-list-operate">
                              <PlusCircleFilled />
                                  添加属性
                              <span>({fields.length}/10)</span>
                            </div>
                          </Form.Item>}
                        </>
                      )}
                    </Form.List>

closertb avatar Jun 28 '23 07:06 closertb