【问题标题】:Async nature of setState() not showing updated props from parent componentsetState() 的异步性质不显示来自父组件的更新道具
【发布时间】:2023-03-03 10:25:01
【问题描述】:

我知道setState() 在 react 中是异步设计的,我明白为什么 - 因为 JS 是单线程的,浏览器也是如此,因此重新渲染是一项昂贵的操作。我有一个非常(似乎是)简单的问题。

我从 Firebase 接收了一些数据,我正在使用 setState() 将该数据设置为组件状态,因此我可以将其作为道具发送到 About.js 组件。正在发生的事情是引擎跳过了setState()(自然),因为它是异步的,并将道具注入About.js 组件。 About.js 组件内的 props 为 null,因为它从最初设置为 null 的父组件接收初始 props。

我尝试了整个回调方法,但我被这个小怪癖困住了(我希望他们在路上添加一个操作来选择 setState() 的同步和异步)。

不管怎样,代码如下——非常简单。提前感谢您的帮助!

App.js

class App extends React.Component {

constructor(props) {
    super(props);

    this.state = {
        home_skills: null
    }

    this.sendSkillProps = this.sendSkillProps.bind(this);
}

sendSkillProps(delta) {
    return (previousState, currentProps) => {           
        return {...previousState, home_skills: delta}
    }
}

componentDidMount() {   

    // GET LIST HOME SKILLSET FROM FIREBASE
    const db = firebase.firestore();
    var skillset_ref = db.collection('SOME_COLLEC_ID').doc('SOME_DOC_ID');

    skillset_ref.onSnapshot((doc) => {
        if (doc.exists) {
            this.setState(this.sendSkillProps(doc.data()));
        } 

        else {              
            console.log("No such document!");
        }
    });     

}

render() {
    return (
    <div className="App">
        <Navbar />
        <MainSplash />
        <About madskills={this.state.home_skills} />
    </div>
    );
}} export default App;

About.js

export default class About extends React.Component {
constructor (props) {
    super(props);

    this.state = {}
}

componentDidMount() {       
    console.log(this.props.madskills); // LOGS AS NULL  
}

render() {
    return (
    ...

【问题讨论】:

    标签: javascript reactjs asynchronous setstate


    【解决方案1】:

    在 App.js 文件的 componentDidMount() 中试试这个

    componentDidMount() {   
        // GET LIST HOME SKILLSET FROM FIREBASE
        const db = firebase.firestore();
        var skillset_ref = db.collection('SOME_COLLEC_ID').doc('SOME_DOC_ID');
    
        skillset_ref.onSnapshot( async (doc) => {
            if (doc.exists) {
                await this.setState(this.sendSkillProps(doc.data()));
            } 
            else {              
                console.log("No such document!");
            }
        });     
    }
    

    【讨论】:

    • 不幸的是,这也不起作用,因为我在控制台中收到错误:Can not use keyword 'await' outside an async function
    • @ParthJ,我的错误是我在 componentDidMount 上使用了异步,而不是在胖箭头函数上使用。我编辑了我的帖子。
    【解决方案2】:

    据我所知,setState 的异步性质在这里是无关紧要的。你似乎有过于复杂的事情。这应该有效:

    class App extends React.Component {
    
    constructor(props) {
        super(props);
    
        this.state = {
            home_skills: null
        }
    }
    
    componentDidMount() {   
    
        // GET LIST HOME SKILLSET FROM FIREBASE
        const db = firebase.firestore();
        var skillset_ref = db.collection('SOME_COLLEC_ID').doc('SOME_DOC_ID');
    
        skillset_ref.onSnapshot((doc) => {
            if (doc.exists) {
                this.setState({home_skills: doc.data()});
            } 
    
            else {              
                console.log("No such document!");
            }
        });     
    
    }
    
    render() {
        return (
        <div className="App">
            <Navbar />
            <MainSplash />
            <About madskills={this.state.home_skills} />
        </div>
        );
    }} export default App;
    

    【讨论】:

    • 是的,我知道额外的功能是不必要的(我只是在尝试不同的东西哈哈),但这仍然让我从 About.js 组件中得到 null。
    • @ParthJ 如果您的&lt;About/&gt; 组件紧密依赖于this.state.home_skills,则不要挂载&lt;About/&gt; 组件,直到this.state.home_skills 具有除null 之外的其他值。
    • @hussain.codes 我喜欢这个主意,我试试看...谢谢。
    【解决方案3】:

    感谢@hussain.codes,这成功了(也感谢其他人!):

    render() {
        return (
        <div className="App">
            <Navbar />
            <MainSplash />
            {
                this.state.home_skills != null ? <About madskills={this.state.home_skills} /> : <h1>Loading...</h1>
            }
        </div>
        );
    }
    

    【讨论】:

      猜你喜欢
      • 2020-01-31
      • 1970-01-01
      • 2017-10-24
      • 1970-01-01
      • 1970-01-01
      • 2019-08-31
      • 2019-09-22
      • 2017-12-28
      • 2018-07-02
      相关资源
      最近更新 更多