在检索数据库数据之前反应渲染

时间:2021-03-01 22:07:29

标签: reactjs mongodb react-hooks use-effect

我正在编写一个应用程序,用于拉取我的 GitHub 存储库并显示其中的某些信息(描述等)。该应用程序设置为如果我没有“初始化”(意味着我还没有发送帐户),那么我将被迫进入“CreateAccount”页面。 “初始化”的状态保存在本地存储中。但是,如果其他人想要查看该应用程序,它们将不会被“初始化”,因此我需要再次检查以查看数据库中是否有任何内容(每个存储库的记录)。如果是这样,那么查看器应该被“初始化”并发送到主页。所有这些都在 App 组件中完成:

const App = () => {
   const setupCtx = useContext(SetupContext);
   const devCtx = useContext(DevDataContext);

  // variable to control routing
  let initialized = null;
  
  if (localStorage.getItem("jtsy-signin") === "true") {
    initialized = true;
  } else {
    API.findRepo()
      .then((repo) => {
        console.log('APP found 1 repo', repo)
        if (repo) {
          initialized = true
          localStorage.setItem('jtsy-signin', 'true')
          console.log('1 REPO initialized', initialized)
        } else {
          initialized = false;
        }
      })
  }

  useEffect(() => {
    if (initialized) {
      console.log('APP useEffect signin=true, redirect to Home page');
      if (localStorage.getItem('jtsy-login') === 'true') {
        setupCtx.updateLoggedIn();
      }
      // console.log('APP devUpdated', setupCtx.state.devUpdated)
      if (setupCtx.state.devUpdated) {
        API.getActiveDevData().then((activeDevData) => {
          // console.log('APP activeDevData', activeDevData.data);
          const developerData = {
            developerLoginName: activeDevData.data.developerLoginName,
            developerGithubID: activeDevData.data.developerGithubID,
            repositories: activeDevData.data.repositories,
            fname: activeDevData.data.fname,
            lname: activeDevData.data.lname,
            email: activeDevData.data.email,
            linkedInLink: activeDevData.data.linkedInLink,
            resumeLink: activeDevData.data.resumeLink,
            active: true
          }
          console.log('APP after DB call', developerData)
          devCtx.updateDev(developerData)
          setupCtx.updateInitialized();
          setupCtx.updateDevUpdated(false)
        })
      }
    };
  }, [setupCtx.state.devUpdated])

  return (
    <div className='App'>
      <React.Fragment>
        <Router>
          <Switch>
            {console.log('IN APP SWITCH initialized', initialized)}
            {initialized ? (
              <Route exact path="/" component={Home} />
            ) : (
                <Route exact path="/" component={CreateAccountComp} />
              )}
            <Route exact path="/contact" component={Contact} />
            <Route exact path="/about" component={About} />
            <Route exact path="/developer" component={Developer} />
            <Route exact path="/login" component={LoginModal} />
            <Route exact path="/logout" component={LogoutModal} />
            <Route exact path="/signin" component={CreateAccountComp} />
            <Route exact path="/settings" component={Settings} />
            <Route component={NoMatch} />
          </Switch>
        </Router>
      </React.Fragment>
    </div >
  );
};

导出默认应用;

变量 'initialized' 控制是呈现主页还是 CreateAccount 页面。如代码所示,首先检查本地存储,如果那里有值,则将 'initialized' 设置为 'true' 并呈现主页。这工作正常。但是,如果本地存储中没有值,我接下来调用 findRepo(),它会在 Mongo 数据库中执行 .findOne()。然后,相应地设置 'initialized' 的值。从数据库获得响应的延迟太长。如果本地存储中没有值,则在呈现时初始化为 'null',因此应用程序始终会转到“CreateAccount”页面。我可以看出数据库调用正在正确响应并且初始化设置为“true”,但为时已晚(CreateAccount 已呈现)。

我尝试将数据库调用放在 useEffect 和单独的 useEffect 中,但都没有奏效。我需要更好的方法来完成这项工作。

1 个答案:

答案 0 :(得分:1)

因此,我对您的代码进行了一些检查,并提出了一个解决方案,可以在状态中添加加载标志,并在我们等待任何类型的更新时使用它来呈现加载屏幕。

在等待更新时,您可以将此加载屏幕设为您想显示的任何内容。

以下是所有在 App.js

中所做的代码更改
// add isLoading flag to state
const [state, setState] = useState(
  {
     loggedIn: null,
     sync: false,
     initialized: null,
     isLoading: true
  }
)

在调用 setState 时,将 isLoading 标志更新为 true。

// line 55 in App.js
setState({
  ...state,
  initialized: true,
  isLoading: false
})
// line 75
setState({
  ...state,
  initialized: true,
  isLoading: false
})
// line 103
setState({
  ...state,
  initialized: false,
  isLoading: false
})

然后是 return 更新。

{state.isLoading && <div>Loading...</div>}
<Route exact path="/" component={state.initialized ? Home : CreateAccountComp} />

通过这些更改,加载屏幕将在我们等待 initialized 的任何类型更新时显示。然后主屏幕将在更新为 true 或创建帐户页面是否更新为 false 时显示。