简体   繁体   English

如何通过在 ComponentDidMount() 中调用的函数访问状态集

[英]How to access state set through a function which is called in ComponentDidMount()

I have a function called calendarLogicHandler() which sets state , spreading a whole month into it.我有一个名为calendarLogicHandler()的函数,它设置state ,将整个月扩展到它。 I called it inside componentDidMount() .我在componentDidMount()调用了它。

the state set works on the calendar app which I am working on. state集适用于我正在开发的日历app This calendar tool will be part of a yoga classes app .这个日历工具将成为瑜伽课程app

then on the week View Mode of the tool, which displays all of events of a single week, I call weekAgendaLogicHandler() , which filters the current week of the current month and displays it on the app .然后在显示一周所有事件的工具的周视图模式上,我调用weekAgendaLogicHandler() ,它过滤当月的当前周并将其显示在app The state for the current week and current month are manipulated further ahead in my logic, but there is no point in displaying this here.当前周和当前月的state在我的逻辑中被进一步操纵,但在这里显示它没有意义。

The issue is:问题是:

I cannot access this.state.currrentMonth on ComponentDidMount() and somehow I see that when I try to console.log(this.state.currentMonth) on render() I see that it renders this.state.currentMonth twice blank, then, on the third re-rendering it finally gets the this.state.currentMonth set by calendarLogicHandler() .我无法在ComponentDidMount()上访问this.state.currrentMonth并且不知何故我看到当我尝试在render()console.log(this.state.currentMonth) render()我看到它呈现this.state.currentMonth两次空白,然后,在第三次重新渲染时,它最终获得了由calendarLogicHandler()设置的this.state.currentMonth

current month in render() []
current month in render() []
getting current month in componentDidMount []
current month in render() [Array[7], Array[7], Array[7], Array[7], Array[7]]
current month in render() [Array[7], Array[7], Array[7], Array[7], Array[7]]
[]

How could I properly use this function so I can call weekAgendaLogicHandler() without having it called inside the callback function of this.setState({currentMonth}) , and setting my state before the rendering phase, in other words, before componentdidmount ?我怎样才能正确使用这个函数,这样我就可以调用weekAgendaLogicHandler()而不在this.setState({currentMonth})callback functioncallback它,并在渲染阶段之前设置我的状态,换句话说,在componentdidmount之前?

the code is here and below:代码在这里和下面:

import React from "react";
import "./styles.css";

export default class App extends React.Component {
  state = {
    currentWeek: [],
    currentMonth: [],
    monthGetter: new Date().getMonth(),
    yearGetter: new Date().getFullYear()
  };

  componentDidMount() {
    this.calendarLogicHandler();
    this.weekAgendaLogicHandler();
    console.log(
      "getting current month in componentDidMount",
      this.state.currentMonth
    );
  }

  weekAgendaLogicHandler = () => {
    let currentWeek = this.state.currentMonth
      .filter(week => week.includes(new Date().setHours(0, 0, 0, 0)))
      .flat();
    this.setState({ currentWeek }, () => console.log(this.state.currentWeek));
  };

  calendarLogicHandler = () => {
    const oneDay = 86400000;
    const lastDayOfTheMonth = new Date(
      this.state.yearGetter,
      this.state.monthGetter + 1,
      0
    ).getDate();
    let currentMonth = [
      new Date(this.state.yearGetter, this.state.monthGetter, 1).valueOf()
    ]; //starts on month day 1
    for (let i = 1; i < lastDayOfTheMonth; i++) {
      //push the entire month
      currentMonth.push(Math.max.apply(null, currentMonth) + oneDay);
    }
    //localize the first date of the month dates array and check what day of the week it is
    //spread the days of the week, which are the remaining days of prev month to fill calendar first week
    for (let i = new Date(Math.min(...currentMonth)).getDay(); i > 0; i--) {
      currentMonth.unshift(Math.min.apply(null, currentMonth) - oneDay);
    }
    //spread the days of the week, which are the remaining days of prev month to fill calendar last week
    for (let i = new Date(Math.max(...currentMonth)).getDay(); i < 6; i++) {
      currentMonth.push(Math.max.apply(null, currentMonth) + oneDay);
    }
    let monthInWeeks = [];
    for (let i = 0; i < currentMonth.length; i += 7) {
      let chunk = currentMonth.slice(i, i + 7);
      monthInWeeks.push(chunk);
    }
    currentMonth = monthInWeeks;
    this.setState({ currentMonth });
  };

  render() {
    console.log("current month in render()", this.state.currentMonth);
    return (
      <div className="App">
        <h1>Testing componentDidMount</h1>
      </div>
    );
  }
}

This is the way how react works.这就是反应的工作方式。

Lifecycle render() method gets called on every update. Lifecycle render()方法在每次更新时都会被调用。 And also it gets called before componentDidMount .而且它在componentDidMount之前被调用。 According to the lifecycle name componentDidMount means function getting called after component got mounted.根据生命周期名称componentDidMount表示在组件挂载后调用函数。 And since component got already mounted , so render() method already got called before componentDidMount method.由于组件已经mounted ,因此在componentDidMount方法之前已经调用了render()方法。

So, first time when you are getting blank data ie, before componentDidMount , render() is getting called with the initial state ie, []因此,当您第一次获取空白数据时,即在componentDidMount之前, render()使用初始状态调用render() ,即[]

Second time again, probably something is getting updated probably in weekAgendaLogicHandler() function due to which again render() is getting called with blank [] array ie., the initial state.第二次,可能会在weekAgendaLogicHandler()函数中更新某些内容,因为再次使用空白[]数组调用render() ,即初始状态。

Now, third time , this.setState is happening state is getting updated and then on render() you are getting the required array.现在,第三次,this.setState 正在发生状态正在更新,然后在render()您将获得所需的数组。

So, this is how render() lifecycle method works.所以,这就是render()生命周期方法的工作原理。

Now, if you want to use render only with the data and not null data.现在,如果您只想对数据而不是null数据使用render Then , you can show some kind of loader.然后,您可以显示某种加载程序。

ie, IE,

render(){
  if(this.state.currentMonth.length){
    return(
      <div className="App">
        <h1>Testing componentDidMount</h1>
      </div>
    )
  }
  else{
    return(
      <p>Loading data...</p>
     )
   }
}

Not sure that I understand what do you want to accomplish?不确定我是否理解您想要完成的任务? Maybe to see how state looks like after this.calendarLogicHandler(); this.weekAgendaLogicHandler();也许看看this.calendarLogicHandler(); this.weekAgendaLogicHandler();之后状态的样子this.calendarLogicHandler(); this.weekAgendaLogicHandler(); ? ?

If that is the case use componentDidUpdate .如果是这种情况,请使用componentDidUpdate In componentDidMount you can only see how state looks like at the time component get mounted in the dom.componentDidMount您只能看到组件在 dom 中安装时的状态。

So it doesn't matter that you are doing console.log in this order:因此,您按以下顺序执行console.log并不重要:

this.calendarLogicHandler();
this.weekAgendaLogicHandler();
console.log(
  "getting current month in componentDidMount",
  this.state.currentMonth
);

... you are still logging the state as it was before calendarLogicHandler & weekAgendaLogicHandler are fired. ...您仍在记录在calendarLogicHandlerweekAgendaLogicHandler被触发之前的状态。

Update:更新:

If you don't wan't to call weekAgendaLogicHandler in componentDidMount (because you don't already have state in shape you need), than you can use something like this:如果你不想在componentDidMount调用weekAgendaLogicHandler (因为你还没有你需要的状态),那么你可以使用这样的东西:

componentDidUpdate(prevProps, prevState) {
 if(/* check that state is previously updated by `calendarLogicHandler` */) {
  this.weekAgendaLogicHandler();
 }
}

But, using a lot timing (hooking into lifecycle events) can make your code unnecessary complex.但是,使用大量时间(挂钩生命周期事件)会使您的代码变得不必要的复杂。 If I were you, would choose to use setState callback to call this.weekAgendaLogicHandler() ;如果我是你,会选择使用setState回调来调用this.weekAgendaLogicHandler()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM