V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
GrapeCityChina
V2EX  ›  推广

React Suspense 尝鲜,处理前后端 IO 异步操作

  •  
  •   GrapeCityChina · 2022-06-16 13:47:23 +08:00 · 573 次点击
    这是一个创建于 893 天前的主题,其中的信息可能已经有所发展或是发生改变。

    简单介绍一下 Suspense

    Suspense 主要用来解决网络 IO 问题,它早在 2018 年的 React 16.6.0 版本中就已发布。它的相关用法有些已经比较成熟,有的相对不太稳定,甚至经历了重命名、删除:

    • 在 render 函数中,我们可以写入一个异步请求,请求数据
    • react 会从我们缓存中读取这个缓存
    • 如果有缓存了,直接进行正常的 render
    • 如果没有缓存,那么会抛出一个异常,这个异常是一个 promise
    • 当这个 promise 完成后(请求数据完成),react 会继续回到原来的 render 中(实际上是重新执行一遍 render ),把数据 render 出来
    • 完全同步写法,没有任何异步 callback 之类的东西

    如果你还没有明白这是什么意思那我简单的表述成下面这句话:

    调用 render 函数->发现有异步请求->悬停,等待异步请求结果->再渲染展示数据
    

    看着是非常神奇的,用同步方法写异步,而且没有 yield/async/await ,简直能把人看傻眼了。这么做的好处自然就是,我们的思维逻辑非常的简单,清楚,没有 callback ,没有其他任何玩意,不能不说,看似优雅了非常多而且牛逼。

    Suspense 的主要用法和场景

    在前端开发中,经常会有这样的需求,加载某个界面时,如果界面的资源比较大,前端对数据的处理也需要时间,加载比较慢,这时候我们需要用一个加载动画或者提示,使得交互更加友好。

    一. React18 之前的做法: 在 React18 之前,我们要实现上面这个效果,请求数据或者加载新的组件的时机一般在 componentDidMount ,在 State 中需要一个 flag 变量来记录请求数据的状态,后续手动更改这个状态,非常的不方便。代码如下:

    class App extends Component {
      state = {
    isLoading: false,
      }
    
      componentDidMount() {
        this.setState({
          data: null,
    isLoading: true,
        });
        axios.get('/api/getData').then((data) => {
          this.setState({
            data,
    isLoading: false,
          });
        });
      }
    
      render() {
        return this.state.loading ? '正在加载中...' : (
          <Page data={data} />
        );
      }
    }
    
    

    二. React18 之后: 1.React.lazy React.lazy() 允许你定义一个动态加载的组件。这有助于缩减 bundle 的体积,并延迟加载在初次渲染时未用到的组件

    const SomeComponent = React.lazy(() => import('./SomeComponent'));
    
    
    

    渲染 lazy 组件依赖该组件渲染树上层的 &lt;React.Suspense&gt; 组件。这是指定加载指示器( loading indicator )的方式。 2.React.Suspense React.Suspense 可以指定加载指示器( loading indicator ),以防其组件树中的某些子组件尚未具备渲染条件:

    // 该组件是动态加载的
    const OtherComponent = React.lazy(() => import('./OtherComponent'));
    
    function MyComponent() {
      return (
        // 显示 <Spinner> 组件直至 OtherComponent 加载完成
        <React.Suspense fallback={<Spinner />}>
          <div>
            <OtherComponent />
          </div>
        </React.Suspense> 
      );
    }
    
    

    Suspense 尝鲜:配合前端表格组件处理前后端 IO 异步操作

    因为没有后端逻辑,前端表格组件主要用于在前端对 Excel 、Grid 表格数据在线编辑和展示,而利用 Suspense 的技术特点,便可以轻松实现前后端 IO 异步操作:

    const PureSpread = React.lazy(() => import('./components/pureSpread'))
    const SpreadDesigner = React.lazy(() => import('./components/designer'))
    const {Content,Header} = Layout
    
    
    
    const App = () => (
      <Layout className="app">
         <IndexSider/>
         <Layout>
            <Content className="index-content">
              <HashRouter>
                  <Switch>
                    <Suspense fallback={<div>loading...</div>}>
                      <Route exact path="/" component={PureSpread}/>
                      <Route exact path="/designer" component={SpreadDesigner}/>   
                    </Suspense>
                  </Switch>
              </HashRouter>
            </Content>
            <IndexFooter/>
         </Layout>
      </Layout>
    )
    
    

    看一下效果:

    本文 Demo:https://gcdn.grapecity.com.cn/forum.php?mod=attachment&aid=MjEyNzM4fDI0MzNlYTIyfDE2NTM4OTI4Mzh8MXwxNDc4NTk%3D

    了解更多在线 demo: https://demo.grapecity.com.cn/spreadjs/gc-sjs-samples/index.html

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3692 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 00:51 · PVG 08:51 · LAX 16:51 · JFK 19:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.