【问题标题】:React not updating data on parent component after child component form submit子组件表单提交后反应不更新父组件上的数据
【发布时间】:2021-04-11 05:21:39
【问题描述】:

我有一个父组件,在提交子组件上的表单时应该更新它。子组件提交表单时,调用了fetchData函数,但是这里父组件没有更新数据,需要刷新页面才能更新数据:

{JSON.stringify(data)}

我无法将 setState 中的 数据 添加到 useEffect,因为它会创建一个无限循环。

从子组件提交表单时,如何更新父组件上的数据?

父组件

export function ParentComponent() {
    const [data, setData] = useState(null);

    const fetchData = async () => {

        const result = await axios(
          '/api/info/'
          );
          setData(result.data)
    }

    useEffect(() => {
        fetchData();
      },[]);


      return (
        <div>
            <h1>
                Parent Page
            </h1>
            
            {JSON.stringify(data)}

            <ChildComponent dataUpdated={fetchData} />
        </div>
    )
}

子组件

export function ChildComponent(props) {
    const [formData, setFormData] = useState('');

    const handleSubmit = evt => {
            evt.preventDefault();
            axios.post(`/api/info/create`,
                        {formData}
                  )
                  .then(response => { return response.data })
                  .then(props.dataUpdated()) // calling this function does not update the data on the parent component
        }
        
    return (
        <div>
            <h1>
                Child Component
            </h1>

            <form className={classes.form} onSubmit={handleSubmit}>
                    <TextField value={formData.number}
                        id="filled-number"
                        label="number"
                        type="number"
                        onChange={evt => setFormData({...formData, number: evt.target.value})}
                    />

                    <Button
                        type="submit"
                    >
                        Submit
                    </Button>
            </form>
        </div>
    )
}

【问题讨论】:

  • 孩子中最后一个then应该是props.dataUpdated之后没有()
  • @fast-reflexes,这行得通,谢谢,但为什么行得通?没有括号怎么调用函数表达式?
  • 我相信我找到了原因。由于函数被热切地评估,我编写的函数会在 then 被调用之前被调用。 stackoverflow.com/a/52769736/3856624
  • 答案是.then 将函数作为参数,当您执行props.dataUpdated() 时,您运行该函数并为then 提供它的返回值,以便在它应该运行的时候运行。 fetchData 的返回值是undefined,因此您将undefined 作为参数传递给then,这当然是行不通的。当您删除括号时,您为 then 提供了一个带有 0 个参数的函数,该函数在应该运行时运行良好。
  • @fast-reflexes,如果您将此作为答案,我会接受。谢谢你的信息。

标签: javascript reactjs asynchronous react-hooks


【解决方案1】:

您必须从该行中删除括号:

.then(props.dataUpdated())

所以它是:

.then(props.dataUpdated)

为什么?

这是Promises 的一个常见错误(我认为它是从axios.post() 返回的),即我们倾向于忘记thencatchfinally 函数的参数Promise 应该是在 Promise 返回时异步执行的函数。

否则,Promise 就像一个常规类/对象,在这种情况下,您将使用不同的参数同步运行其 then 函数两次。但是像往常一样,当我们向一个函数提供一个参数时,该函数本身就是一个函数调用,这个调用首先执行,它的返回值作为实际参数给出。

所以当你这样做时:

.then(props.dataUpdated())

...您正在同步(即在Promise 返回之前)运行props.dataUpdated 函数并将其返回值作为参数传递给then。由于props.dataUpdated = fetchData 返回undefined(没有返回值),这和:

.then(undefined)

...这行不通。

请记住,参数函数应该在稍后阶段(当 Promise 解析时)异步执行,但现在您立即运行它,然后让带有 undefinedthen 函数在Promise 解决。由于更改的状态尚未发生,因此在这个过早的时间运行更新函数不会产生任何结果,并且由于稍后将 undefined 作为函数运行也不会产生任何结果,因此您会得到一个 UI,即未按预期更新(当then 尝试将undefined 作为函数运行时,控制台中也可能出现错误)。

总结一下……

...您需要为then 提供一个可执行函数,其中包含当Promise 异步返回时要运行的逻辑(就像您已经在第一个then 中所做的那样)。最简单的方法是:

.then(props.dataUpdated) // forwarding the function given in props

...但你也可以这样做:

.then(res => props.dataUpdated()) // arrow function calling the function given in props

.then(res => { props.dataUpdated() }) // arrow function with body calling the function given in props

...如果您想对上一步的输入(即从上一个then (response.data) 返回的值)做一些事情,这会更方便。

参考文献

【讨论】:

    猜你喜欢
    • 2019-12-04
    • 2021-07-07
    • 2018-04-22
    • 2021-09-29
    • 2020-11-21
    • 2017-09-10
    • 2018-11-18
    • 1970-01-01
    • 2017-05-05
    相关资源
    最近更新 更多