Ошибка при отображении @вычисленного значения с использованием mobx и nextjs

#reactjs #next.js #server-side-rendering #mobx

#reactjs #next.js #рендеринг на стороне сервера #mobx

Вопрос:

У меня ошибка в моем приложении с использованием mobx и NextJS.

Ошибка, показанная в инструментах разработки, является:

 index.js:1 Warning: Did not expect server HTML to contain the text node "3" in <h1>.
    in h1 (at pages/index.tsx:18)
    in div (at pages/index.tsx:17)
    in Post (created by inject-with-notesStore(Post))
    in inject-with-notesStore(Post) (at _app.tsx:32)
    in Container (at _app.tsx:31)
    in MobXProvider (at _app.tsx:30)
    in CustomApp
    in Container (created by AppContainer)
    in AppContainer
  

Я пытаюсь протестировать ответ от функции @computed с именем ‘test’, объявленной в testStore.ts.

Я ожидаю получить значение ‘3’ внутри ‘Pages /index.tsx’ в качестве длины @observable testArray, который объявлен в testStore.ts . Вместо этого я не получаю никакого значения.

Есть идеи, почему это происходит?

мой код :

testStore.ts

 import { observable, action, computed } from "mobx";
import { fetchNotes } from "../api";

export interface INotes {
  createdAt?: number;
  updatedAt?: number;
  __v?: number;
  _id?: number;
  title: string;
  todos: {
    description: string;
    checked: boolean;
    id: boolean;
  }[];
}

class NotesStore {
  @observable notes: INotes[] = observable([]);
  @observable testArray = ["a", "b", "c"];
  
  constructor(initialData = {} as { notes: INotes[] }) {
    this.notes = initialData.notes;
  }

  async fetch() {
    const processedResponse = await fetchNotes();
    this.setNotes(processedResponse);
  }

  @computed get test() {
    return this.testArray.length;
  }

  @action setNotes(notes) {
    this.notes = notes;
  }
}

export default NotesStore;
  

stores.ts

 import { useStaticRendering } from "mobx-react";

import NotesStore, { INotes } from "./testStore";

const isServer = typeof window === "undefined";
useStaticRendering(isServer);

let store = null;

export default function initializeStore(
  initialData = { notesStore: {} as NotesStore }
) {
  if (isServer) {
    return {
      notesStore: new NotesStore(initialData.notesStore),
    };
  }
  if (store === null) {
    store = {
      notesStore: new NotesStore(initialData.notesStore),
    };
  }

  return store;
}
  

страницы/_app.tsx

 import React from "react";
import App, { Container } from "next/app";
import { Provider } from "mobx-react";

import initializeStore from "../mobx/stores";

class CustomApp extends App {
  mobxStore: any;
  static async getInitialProps(appContext) {
    const mobxStore = initializeStore();
    appContext.ctx.mobxStore = mobxStore;
    const appProps = await App.getInitialProps(appContext);
    return {
      ...appProps,
      initialMobxState: mobxStore,
    };
  }

  constructor(props) {
    super(props);
    const isServer = typeof window === "undefined";
    this.mobxStore = isServer
      ? props.initialMobxState
      : initializeStore(props.initialMobxState);
  }

  render() {
    const { Component, pageProps } = this.props;
    return (
      <Provider {...this.mobxStore}>
        <Container>
          <Component {...pageProps} />
        </Container>
      </Provider>
    );
  }
}
  

страницы/index.tsx

 import React, { Component } from "react";
import { inject, observer } from "mobx-react";

@inject("notesStore")
@observer
class SampleComponent extends Component {
  static async getInitialProps({ mobxStore, query }) {
    await mobxStore.notesStore.fetch();
    return { notesStore: mobxStore.notesStore };
  }

  render() {
    const { notesStore }: any = this.props;
    debugger;

    return (
      <div>
        <h1>{notesStore.test}</h1>
      </div>
    );
  }
}

export default SampleComponent;
  

Ответ №1:

Моим решением был рефакторинг моего кода и использование оболочки next-mobxhttps://github.com/nghiepit/next-mobx-wrapper

Это единственный способ, которым я мог бы использовать mobx и nextjs и наслаждаться функциональностью обоих.