React中当我改变传递给组件的props时,组件不更新

10

我有一个功能组件,它有一个子组件。子组件显示一些文本,这些文本通过props从父组件传递给它。当我更改父组件中的文本并将其传递下来时,子组件仍然保留旧的文本。

以下是父组件MainPage的最小可重现示例。

function MainPage(){
    let text = "This is the original text";
    setTimeout(function(){ text = "This is the new text" }, 3000);
    return(<DisplayText text={text} />);
}

以下是显示文本。

function DisplayText(props){
    return(<p>{props.text}</p>)
}
如何更新子组件,以便在3秒后显示“这是新文本”而不是“这是原始文本”?谢谢!

3
您必须将相关代码作为 [mcve] 添加到您的问题中。 - Andy
你如何更改文本?我怀疑你只是在突变传递的props,这在React中是行不通的。 - HMR
1
你好,能否加上你的代码以便别人帮助你?谢谢。 - Alberto Perez
2
已添加最小可重现示例代码。 - Dark Programmer
2个回答

10
一个组件只会在其state改变或props改变时更新一次。state是组件重新呈现时记住的变量或变量集。所有其他变量将在组件重新呈现后返回其默认值。您可以将其视为组件的内存。
因此,在您的情况下,更改text变量不会更新parent的状态,因此不会重新呈现组件,这反过来也不会重新呈现和更新子组件。
如果要使父组件更新其状态(并更新子项的props),则需要像这样声明文本变量:
const [text, setText] = React.useState("This is the original text");

文本是你的变量,它现在包含在你的组件状态中,并且在组件重新渲染时将被记住。你可以给它任何想要的名称。

setText是一个函数,它更新你的text变量,并重新渲染你的组件及其子组件。你可以给它任何想要的名称。

"这是原始文本"是你的初始状态,也是text变量的初始值。

要更新你的状态,你可以像这样做:

setText("This is the new text");

那么在您的情况下,它将看起来像这样:

function MainPage(){
    const [text, setText] = React.useState("This is the original text");

    React.useEffect(() => {
        const timeout = setTimeout(function(){
            setText("This is the new text")
        }, 3000);

        return clearTimeout(timeout)
    }, []);

    return(<DisplayText text={text} />);
}

useEffect是必要的,可以在组件加载时定义setTimeout。它可用于在某个变量(在[]括号中定义)更新时立即执行一些代码。例如:如果您像这样编写:

React.useEffect(() => {
    // execute some code
}, [text])

在您的text变量更改时,它将立即执行一些代码。将[]括号留空以仅在组件挂载和卸载时触发useEffect

useEffect钩子内声明setTimeout,这在此情况下设置了您的计时器,使其在组件挂载时立即启动。

您的useEffect中的return方法会在组件卸载时清除您的超时。这将防止您的计时器在组件卸载后无限期运行。


是的,如果不使用一些React工具来修改状态/属性,这将是不可能完成的。 - Alberto Perez

2

为了让变量在子组件中监听属性,它应该是父组件状态的一部分。你编写的父组件是错误的,因为你使用let定义了一个静态变量。

你有两个选择,要么按照Luze发布的React Hooks示例(缺少触发组件加载后的setTimeout函数的useEffect函数)操作,要么将父组件转换为类,如下所示:

import React from 'react';

class MainPage extends React.Component {
  state={
      text: "This is the original text",
  };

  componentDidMount(){
     setTimeout(()=> { this.setState({
        text: "This is the new text"
      }) 
     }, 3000);
  }

  render(){
    return(<DisplayText text={text} />);
  }

}

你说得对,是我的错。我会相应地更新我的答案。谢谢你的建议。 - Luïs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接