如何在渲染之前设置父状态?

我知道这是一个很长的介绍,但是我在这里很难弄清楚自己

在我正在使用的Next.js应用程序中,我需要在具有特定div的{​​{1}}上设置CSS网格布局。我使用样式组件id进行此操作。我希望该App组件的每个子组件都能够更改此网格布局(可以选择传入替代CSS值)。

我已经在状态下设置了默认的网格CSS值(如果未由孩子调用该函数,则回退)。我创建了一个类方法(createGlobalStyle),该方法可以使用接收到的参数设置布局状态。我使用React Context将对该函数的引用传递给每个子组件。

在我的子组件中,我现在可以导入此上下文并使用其他布局调用该函数。有用。但是...当我第一次刷新页面时,在将子组件布局应用于根div之前,后备布局会闪烁一秒钟。

换句话说,在首先渲染时,使用后备值来渲染App组件,然后通过调用函数来更改子组件,该函数会更改App组件的状态,从而触发重新渲染。然后在第二次渲染时,将以正确的布局渲染App组件。
我真的希望App组件在第一次渲染时渲染孩子提供的布局(如果提供),而无需先渲染后备。请帮助我实现这一目标。

P.S。我正在使用服务器端渲染,尽管我认为这没有任何作用

setLayout
// App component
// I have trimmed a lot of non relevant logic 
export const LayoutSetter = createContext((layout: Layout): void => {});

export default class App  {
  constructor(props: AppProps) {
    super(props);

    this.state = {
      layout: {
        columns: "100vw",rows: "50px 50px",areas: "
         header 
         content
        ",},};
  }

  setLayout(layout: Layout): void {
    this.setState({ layout: layout });
  }

  render(): JSX.Element {
    const { Component,pageProps } = this.props;

    const __NextStyle = createGlobalStyle`
      #__next {
        display: grid;

        grid-template-columns: ${this.state.layout.columns};
        grid-template-rows: ${this.state.layout.rows};
        grid-template-areas: "${this.state.layout.areas}";
      }
    `;

    const setter = (layout: Layout): void => this.setLayout(layout);

    return (
      <>
        <__NextStyle />
        <LayoutSetter.Provider value={setter}>
          <Component {...pageProps} />
        </LayoutSetter.Provider>
      </>
    );
  }
}
zz19860418 回答:如何在渲染之前设置父状态?

正在发生的事情是,由于子级是App渲染的产物,因此直到App渲染之后,子项才会变热。到那时,App已经使用默认布局呈现。

  1. App渲染(默认)
  2. App渲染的一部分触发Child的渲染
  3. Child中,执行setLayout
  4. App布局已更新。

不幸的是,您要达到的目标(至少是您达到目标的方式)无法完成。您可以做的是在调用setLayout之前没有默认布局。基本上,在子级中调用setLayout之前,不要渲染特定的布局。然后,在setLayout中,您可以执行以下操作。

  setLayout(layout: Layout): void {
   if (layout){
     this.setState({ layout: layout });
   } else {
     this.setState({ 
        layout: {
           columns: "100vw",rows: "50px 50px",areas: "
             header 
             content
           ",} 
     });
   }
  }

初始状态可能是

layout: {
    columns: "",rows: "",areas: "
      header 
      content
    ",},...

但是随后您会遇到其他样式问题(例如,没有布局可能看起来很糟糕)。您可以通过将NextStyle组件的不透明度设置为0this.state.layout.columns.length > 0来弥补这一点。

var opacity = this.state.layout.columns.length > 0 ? 1 : 0;

const __NextStyle = createGlobalStyle`
      #__next {
        display: grid;
        opacity: ${opacity};
        grid-template-columns: ${this.state.layout.columns};
        grid-template-rows: ${this.state.layout.rows};
        grid-template-areas: "${this.state.layout.areas}";
      }
    `;

这样,至少在调用setLayout之前,您什么都不显示。我不确定您是否宁愿您描述的默认布局稍作改动,但这可能是您最好的选择。

本文链接:https://www.f2er.com/3100675.html

大家都在问