美文网首页让前端飞React.js
【2018 react 大会分享】90%清理你的react组件

【2018 react 大会分享】90%清理你的react组件

作者: mytac | 来源:发表于2018-11-07 10:30 被阅读19次

    获得更好的阅读体验->请戳我!
    2018 react conf在今年十月底于las vegas举行,其中主讲人Ryan Florence,演示了使用最新版本的react其中的几个hooks api可以大幅减少react functional 组件的代码量,本篇文章将围绕这个内容进行补充和示范。(在文章的结尾有大会的油管连接,没有梯子的小伙伴可以在b站上自行搜索)。

    比如现在有个需求,需要监听键盘输入内容,显示在屏幕的某块可见范围中,效果如下:

    demo

    以下代码基于create-react-app创建。

    使用稳定版本react实现(v15)

    class App extends Component {
      constructor(props) {
        super(props)
        this.state = {
          words: ''
        }
        this.keyFunc = this.keyFunc.bind(this)
      }
    
      componentDidMount() {
        window.addEventListener('keypress', this.keyFunc)
      }
    
      componentWillUnmount() {
        window.removeEventListener('keypress', this.keyFunc)
      }
    
      keyFunc(e) {
        this.setState(prev => ({
          words: prev.words + e.key
        }))
      }
    
      render() {
        const { words } = this.state
        return (
          <div className="App">
            <header className="App-header">
              <img src={logo} className="App-logo" alt="logo" />
              <p>{words}</p>
            </header>
          </div>
        );
      }
    }
    

    我们会发现仅仅为了绑定监听函数和使用state,就要调用两个钩子函数和声明为类组件,是不是有点小题大做了??那么我们看一下v16的react给我们带来的简洁高效!

    使用alpha版本(v16.7)

    首先安装

    yarn add react@next,react-dom@next
    
    import React, { useState, useEffect } from 'react';
    
    function setIt(initWords) {
      const [words, setWords] = useState(initWords);
      const listener = (e) => { setWords(prev => (prev + e.key)) }
      useEffect(() => {
        window.addEventListener('keypress', listener);
        console.log('aaa')
        return () => window.removeEventListener('keypress', listener);
      }, [])
      return words
    }
    
    function App() {
      const words = setIt('')
      return (
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <p>{words}</p>
          </header>
        </div>
      );
    }
    

    看啊!虽然是functional component,却可以产生和class组件一样的效果,而且减少了代码量。那么useStateuseEffect到底是干啥的呢?往下翻OVO

    api

    useState

    类似于setState,但不支持state object扩展,如下

    setState(prevState => {
      // Object.assign would also work
      return {...prevState, ...updatedValues};
    });
    

    useState用法如下:

    const [state, setState] = useState(initialState);
    

    延迟初始化

    如果initState是需要昂贵计算的结果,它也可以被延时提供,如下。

    const [state, setState] = useState(() => {
      const initialState = someExpensiveComputation(props);
      return initialState;
    });
    

    useEffect

    useEffect(didUpdate);
    

    使用useEffect,传递给它的函数将会在组件渲染到屏幕后运行。

    在从屏幕上卸载组件之前,要清除监听器或者定时器以避免内存泄漏。useEffect可以返回一个清除函数,来完成这项操作,如:

    useEffect(() => {
      const subscription = props.source.subscribe();
      return () => {
        // Clean up the subscription
        subscription.unsubscribe();
      };
    });
    

    触发effect的时机

    在组件每次渲染完毕之后触发effect,在此期间如果有输入变化,总是会重新建立effect。这里就引出了useEffect的第二个参数,他是一个数组类型,指的是产生effect所依赖的值。

    比如我们将上述代码改为

    useEffect(() => {
        window.addEventListener('keypress', listener);
        console.log('aaa')
        return () => window.removeEventListener('keypress', listener);
      }, [state.words])
    

    指该effect依赖于state.effect这个字段,如果它变化的话,将会触发effect函数,在此例中只要输入,就会触发effect中的函数(如果你尝试此例的话,当你的键盘在输入时,会看到控制台在打印aaa)。那么,如果我们传入空数组,useEffect只会在componentDidMountcomponentWillUnmount阶段触发,也就是仅仅触发一次(这时控制台只打印了一次aaa)。

    参考链接

    1. react-conf-2018
    2. youtube视频 -- 90% Cleaner React - Ryan Florence - React Conf 2018
    3. react api-【userState】
    4. react conf 2018主站

    最后请大家关注我的订阅号获得更加及时的推送~

    那屋水泡

    相关文章

      网友评论

        本文标题:【2018 react 大会分享】90%清理你的react组件

        本文链接:https://www.haomeiwen.com/subject/jqmmxqtx.html