react第一次渲染时,页面数据如何处理?

问题如下:

第一次进入到页面的时候,因为需要去fetch数据,所以会在没数据的情况下有一次渲染,等fetch成功后,会再一次进行渲染。

怎么解决第一次进入页面没数据的情况下,页面渲染时不报错

阅读 20k
11 个回答
constructor(){
    this.state = {
        isLoading = true,
        data: []
    }
}

render(){
    return (
        {
            this.state.isLoading 
            ? <Loading /> 
            : <Content />
        }
    )
}

加个 loading 的状态.

思路是条件渲染,设置一个判断条件,条件值不同,渲染的组件不同,下面是官网的一个例子

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;

    let button = null;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

参考:https://facebook.github.io/re...

给定同fetch回来的数据格式一样的默认数据,数组使用空数组,对象则属性都需要存在,值为默认值或者空值。

没有的值默认给个空就可以了。例如<p>{data.code ? data.code : ''}</p> 然后在componentDidmount生命周期中去请求数据,然后在setState

可以定义一些默认值,拉取数据时间显示loading

难道你不设置默认值嘛

通过state管理有无数据的渲染内容

fetch(url, method: 'Get')
.then(response => {
if(response){
message.success(请求成功);
return JSON.stringify(response);
}
throw error(请求失败);
})
.then(data => {
dispath(dataAction(data))
})
.catch(e => {
console.log(e)
})

你难道没有设置fetch状态吗?wait, request, success, failure?

新手上路,请多包涵

可以使用fetch-initial-data插件
https://github.com/tzuser/fet...

react服务端渲染首次获取数据

安装

npm install --save fetch-initial-data

使用演示

https://github.com/tzuser/ssr_base

需要首次加载的组件

import {bindActionCreators} from 'redux';
class Home extends Component{
  constructor(props){
    super(props)
    //判断是否是浏览器
    if(typeof window==="object")this.fetchData();
  }
  //fetchData固定名称,必须返回异步,且所有action需要awiat
  async fetchData(){
    await this.props.getDataAct();
  }
  render(){
    let {data}=this.props;
    return <div>首页 {data} </div>
  }
}
const mapStateToProps=(state)=>({
  data:state.config.data
})
const mapDispatchToProps=(dispatch)=>bindActionCreators({
  getDataAct:Acts.getData,
},dispatch)

export default connect(mapStateToProps,mapDispatchToProps)(Home)

服务端

import {getDataFromTree} from 'fetch-initial-data';

const render=async (ctx,next)=>{
  //获取store
  const { store, history } = createServerStore(ctx.req.url);
  const AppRender=(
      <Provider store={store}>
        <ConnectedRouter history={history}>
          <App/>
        </ConnectedRouter>
      </Provider>
  )
  //保证所有请求完成
  await getDataFromTree(AppRender);
  //取得state传入html
  let state=store.getState();
  //开始渲染
  let routeMarkup =renderToString(AppRender)
}

使用演示

https://github.com/tzuser/ssr_base

//方法一:骨架屏或loading图
 {market_topic && market_topic.data.topic_list ? market_topic.data.topic_list.map((item, index) => (
  <a key={index} href={item.link}>
    <li className="topic-item">
      <div className="topic-photo">
        <div className="_3kP-rt0_ _37xwNlCe">
          <i className="_2AmRNPt0" style={{ 'marginTop': '100%' }}></i>
          <div className="_1uN_mkij" style={{ 'backgroundImage': `url(${item.img})`, 'backgroundSize': 'cover', 'backgroundRepeat': 'no-repeat', 'backgroundPosition': 'center center' }}></div>
        </div>
      </div>
    </li>
  </a>
)) : <Skeleton active="true" />}
//方法二:
 {market_topic && market_topic.data.topic_list.map((item, index) => (
  <a key={index} href={item.link}>
    <li className="topic-item">
      <div className="topic-photo">
        <div className="_3kP-rt0_ _37xwNlCe">
          <i className="_2AmRNPt0" style={{ 'marginTop': '100%' }}></i>
          <div className="_1uN_mkij" style={{ 'backgroundImage': `url(${item.img})`, 'backgroundSize': 'cover', 'backgroundRepeat': 'no-repeat', 'backgroundPosition': 'center center' }}></div>
        </div>
      </div>
    </li>
  </a>
)) }
====================
render() {
  const { market_people } = this.props
  return (
    market_people &&
    <section className="user-bar">
      <a className="user-bar-cart" href={market_people.data.cart_url}>
        购物车<em className="user-bar-cart-num">{market_people.data.cart_num ? market_people.data.cart_num : ''}</em>
      </a>
      <i className="user-bar-line"></i>
      <a className="user-bar-people" href={market_people.data.people_url}> 我的豆品</a>
  </section >
  )
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题