我最近将静态导航栏从一般的html元素移到了页面的React渲染中,因为我想将动态加载通知的功能合并到可以在导航中触发的模式中。进行此更改后,我注意到导航页面不会在页面加载时立即显示,而是在componentDidMount() { this.fetchList(); }
完成加载后立即显示。
我个人认为这是因为导航组件是在与该API提取有关的render()
调用中设置的,并且由于在调用之后设置了此类,所以导航将不得不等到提取成功或失败返回。
如果这是真的,那是否意味着我需要将导航设置为更高的级别,以确保在页面加载带有样式和非反应性元素的页面时加载?
这是我的ReactDOM.render()
:
import React from 'react';
import ReactDOM from 'react-dom';
import AnnotationFeedContainer from './components/app/activity-feed/activity-feed.js';
ReactDOM.render(<AnnotationFeedContainer />, document.getElementById('annotation-card'));
这里是<AnnotationFeedContainer />
,它正在渲染我的react元素(<Navigation />
是我希望加载的组件,无论fetchList()
为何,它都应加载):
import React from 'react';
import fetch from 'node-fetch';
import path from 'path';
import Navigation from '../navigation';
import AnnotationSearchForm from './annotation-search-form';
import OnboardingInformation from './onboarding/information';
import ActivityFeedNotifications from './notifications/notifications';
import AnnotationFeed from './annotation-card/annotation-card-feed';
import { API_ROOT } from '../config/api-config';
//GET /api/test and set to state
export default class AnnotationFeedContainer extends React.Component{
constructor(props, context) {
super(props, context);
this.state = this.context.data || window.__INITIAL_STATE__ || { annotations: [], isLoading: true, onboardingWelcome: false, notifications: [] };
}
fetchList() {
fetch(`${API_ROOT}` + '/api' + window.location.search, { compress: false })
.then(res => {
return res.json();
})
.then(data => {
console.log(data);
this.setState({ annotations: data.annotation, user: data.user, csrf: data.csrfToken, isLoading: false, onboardingWelcome: data.onboardingWelcome, notifications: data.notifications, feedPreference: data.feedPreference });
})
.catch(err => {
console.log(err);
});
}
componentDidMount() {
this.fetchList();
}
render() {
if(this.state.feedPreference === 1){
return (
<div>
<Navigation notifications={this.state.notifications}/>
<AnnotationSearchForm />
<div className="activity-feed-container">
<div className="container">
<OnboardingInformation onboarding={this.state.onboardingWelcome}/>
<LoadingIndicator loading={this.state.isLoading} />
<div className="row">
<div className="col-md-12">
<AnnotationFeed {...this.state} />
</div>
</div>
</div>
</div>
</div>
)
} else {
return (
<div className="activity-feed-container">
<div className="container">
<OnboardingInformation onboarding={this.state.onboardingWelcome}/>
<LoadingIndicator loading={this.state.isLoading} />
<div className="row">
<div className="col-md-6 col-md-offset-3">
<AnnotationFeed {...this.state} />
</div>
<div className="col-md-1 col-md-offset-1">
<ActivityFeedNotifications notifications={this.state.notifications} />
</div>
</div>
</div>
</div>
)
}
}
};
//Loading Indicator
const LoadingIndicator = props => {
if(props.loading == true){
return (
<div className="spinner">
<div className="bounce1"></div>
<div className="bounce2"></div>
<div className="bounce3"></div>
<p>Loading...</p>
</div>
)
} else {
return null;
}
}
导航组件:
import React from 'react';
import NotificationPopover from './activity-feed/notifications/notifications-popover';
//Navigation
export default class Navigation extends React.Component {
render() {
return (
<nav className="navbar">
<div className="container-fluid">
<div className="navbar-header">
<button type="button" className="navbar-toggle" data-toggle="collapse" data-target="#navigationLinks">
<span className="icon-bar mobile-nav-toggle"></span>
<span className="icon-bar mobile-nav-toggle"></span>
<span className="icon-bar mobile-nav-toggle"></span>
</button>
<a className="navbar-brand" href="/app"><img src="/images/synotate_logo.svg" className="nav-logo-svg"></img></a>
</div>
<div className="collapse navbar-collapse" id="navigationLinks">
<ul className="nav navbar-nav">
<li className="nav-item">
<a className="nav-link" href="/app">Activity Feed</a>
</li>
<li className="nav-item">
<a className="nav-link" href="/app/settings">Settings</a>
</li>
</ul>
<ul className="nav navbar-nav navbar-right">
<li className="nav-item">
<NotificationPopover notifications={this.props.notifications}/>
</li>
<li className="nav-item">
<a className="nav-link" href="/app/logout">Log Out</a>
</li>
</ul>
</div>
</div>
</nav>
)
}
}
答案 0 :(得分:0)
在您的<AnnotationFeedContainer>
中,您在if(this.state.feedPreference === 1)
方法中有这行render()
。
除非您有一个成功的fetch()
事件来自fetchList()
中的componentDidMount()
,否则该条件将为true;如果此条件返回true
,则将呈现在其括号内,其中包括<Navigation>
组件
否则,您将呈现另一个代码,我猜这是加载指示符,并且在这里,您没有包括Navigation
组件,因此它不会显示。
这是您正在使用的逻辑,您告诉您的应用程序不包含Navigation
组件,除非它获取您的数据,这在逻辑上是可以的!
如果您想以其他方式显示它,则可能要将其从您拥有的if
语句中移出
答案 1 :(得分:0)
似乎您的访存调用负责将feedPreference
变量设置为您的状态。
由于在您的if
条件中使用了此变量,并且在未设置<Navigation/>
时不会呈现feedPreference
组件。
一个简单的解决方案是将<Navigation/>
添加到else
条件中(在<AnnotationFeedContainer/>
的render函数中):
} else {
return (
<>
<Navigation notifications={this.state.notifications}/>
<div className="activity-feed-container">
<div className="container">
<OnboardingInformation onboarding={this.state.onboardingWelcome}/>
<LoadingIndicator loading={this.state.isLoading} />
<div className="row">
<div className="col-md-6 col-md-offset-3">
<AnnotationFeed {...this.state} />
</div>
<div className="col-md-1 col-md-offset-1">
<ActivityFeedNotifications notifications={this.state.notifications} />
</div>
</div>
</div>
</div>
</>
)
}
一种更像“反应式”的操作方式可能是使用以下内容替换整个条件:
return (
<>
<Navigation notifications={this.state.notifications} />
{this.state.feedPreference === 1 && <AnnotationSearchForm />}
<div className="activity-feed-container">
<div className="container">
<OnboardingInformation onboarding={this.state.onboardingWelcome} />
<LoadingIndicator loading={this.state.isLoading} />
<div className="row">
{this.state.feedPreference === 1 ?
<>
<div className="col-md-6 col-md-offset-3">
<AnnotationFeed {...this.state} />
</div>
<div className="col-md-1 col-md-offset-1">
<ActivityFeedNotifications notifications={this.state.notifications} />
</div>
</>
:
<div className="col-md-12">
<AnnotationFeed {...this.state} />
</div>
}
<div className="col-md-6 col-md-offset-3">
<AnnotationFeed {...this.state} />
</div>
<div className="col-md-1 col-md-offset-1">
<ActivityFeedNotifications notifications={this.state.notifications} />
</div>
</div>
</div>
</div>
</>
)
使用内联ifs(&&
)可以避免重复。如果您不能使用片段(<>
是在最新的React版本中添加的),则可以将其替换为<div>
标签