使用 ref 从父函数组件传递时 useState 不更新数据

Posted

技术标签:

【中文标题】使用 ref 从父函数组件传递时 useState 不更新数据【英文标题】:useState not updating data when passing from parent function component using ref 【发布时间】:2021-12-10 02:17:30 【问题描述】:

我正在尝试将数据发送到子函数组件,在该组件中我将表单字段与该数据绑定。它在第一次调用时工作正常,但是当我第二次调用时,数据从不更新状态,它总是显示第一个。

这是使用子组件引用的父组件

export default function Form1() 
    const [count, setCount] = useState(0);
    const [counter, setCounter] = useState(10);

    const AddNewRef = useRef();

    const clickMe=() => 

        setCount(count+1);
        setCounter(counter*2);

        AddNewRef.current.showDrawer(counter*2);

    


    return (
        <div>
            <p>You clicked count: count & counter: counter times</p>
            
                count > 10 ?
                (
                        <p className='red'>your count is greater then 10</p>
                ) :
                (
                    <p className='green'>your count is less then 10</p>
                )
            
            <button onClick=() => clickMe()>
                Click me
            </button>

           
            <AddNew ref=AddNewRef Count=count Counter=counter  />

        </div>
    )

 

这是子组件

const AddNew=forwardRef((props, ref) => 
    const[objCounter, setobjCounter] = useState(null);

    useImperativeHandle(
        ref,
        () => (
            showDrawer(count) 


              setobjCounter(count);
              //only shows at first click at parent, Not updating on 2nd, 3rd click from parent and so on....


          
        ),
    )

return (
    <>
      <Drawer
        title=<span> <i className='fa-solid fa-kaaba' /> Haj Setup Form</span>
        width=window.innerWidth > 900 ? 800 : window.innerWidth - 50
        onClose=onClose
        visible=visible
        bodyStyle= paddingBottom: 80 
        extra=
          <Space>
            <Button onClick=onClose>Cancel</Button>
            <Button onClick=onClose type="primary">
              Submit
            </Button>
          </Space>
        
      >
        <Form 
      style=display: formVisible ? 'block' : 'none'
          form=form
          layout="vertical" 
                onFinish=onFinish
                onFinishFailed=onFinishFailed
                autoComplete="off"
                          
          hideRequiredMark>
            

            <Row gutter=16>
              <Col xs=24 sm=24 md=24 lg=24>

                <Form.Item
                  name="packageName"
                  label="Package Name"
                  rules=[ required: true, message: 'Please enter package name' ]
                  initialValue=objCounter
                  
                  >
                  <Input style=width: '100%'
                         maxLength=100  /> 
                </Form.Item>
              </Col>
            </Row>
        </Form>
      </Drawer>
    </>
  )
);


export default AddNew

【问题讨论】:

所以你想在什么时候更新子组件的本地状态(AddNew)。在父组件中单击按钮?您要发送给showDrawer 的值是多少?据我所知,将状态更新排入队列,但只发送当前状态值。 不清楚您声称没有更新。这是一个正在运行的codesandbox,本地objCounter 状态正在更新。您能否更新您的问题以包含所有相关代码? 我没有看到子组件内部使用了任何 ref。检查反应文档以了解如何正确使用 useImperativeHandle 和 useRef @ABDULLOKHMUKHAMMADJONOV 引用在子组件的useImperativeHandle钩子中使用。 嗨 Drew Reese,我在代码框上做了一些更改,请检查是否有另一个错误 【参考方案1】:

由于状态更新正在工作并且您只是想更新表单字段,您可以使用从useForm 挂钩返回的form 引用来更新表单状态。在这种情况下,请更新 packageName 字段。

const AddNew = forwardRef((props, ref) => 
  const [objCounter, setobjCounter] = useState(13);
  const [visible, setVisible] = useState(false);
  const [formVisible, setformVisible] = useState(true);
  const [form] = Form.useForm();

  useImperativeHandle(ref, () => (
    showDrawer(count) 
      setobjCounter(count);
      setVisible(true);

      form.setFieldsValue(
        packageName: count // <-- update the specific field
      );
    
  ));

  const onClose = () => 
    setVisible(false);
  ;

  return (
    ...
  );
);

【讨论】:

Booooom Booom 非常感谢 Drew。 是的,但是如果 antd form 有任何方法可以一次绑定所有字段,比如 form.setFieldsValues(props?.editData)... ?这将非常容易 它也完成了,很好,它也已解决和增强。 @MuhammadFaheemChughtai 我对 antd 组件不是很熟悉,但我的猜测是 setFieldValues 接受一个键值对对象,代表您的 any 字段,通过name 属性。例如,如果您有 2 个输入,firstNamelastName,那么您可以想象使用 setFieldValues( firstName: 'Drew', lastName: 'Reese' ) 谢谢你,Drew,现在看起来不错,我是 ant 新手,如果有任何问题,我会问你,再次感谢。

以上是关于使用 ref 从父函数组件传递时 useState 不更新数据的主要内容,如果未能解决你的问题,请参考以下文章

将异步结果从父组件传递给子组件反应功能组件

从reactjs中的父组件调用并将参数传递给子组件的函数

即使从父组件传递函数后也无法从子组件更改状态

React(74)--onRef在react中的使用

如何在角度2中将数据从父构造函数传递到子组件

使用 useState 在 React 组件之间传递值