加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

[React] Refactor a Class Component with React hooks to a Fun

发布时间:2020-12-15 20:34:27 所属栏目:百科 来源:网络整理
导读:We have a render prop based?class component that allows us to make a GraphQL request with a given query string and variables and uses a GitHub graphql client that is in React context to make the request. Let‘s refactor this to a function

We have a render prop based?class component that allows us to make a GraphQL request with a given query string and variables and uses a GitHub graphql client that is in React context to make the request. Let‘s refactor this to a function component that uses the hooks useReducer,useContext,and useEffect.

?

Class Based Component:

import {Component} from react
import PropTypes from prop-types
import isEqual from lodash/isEqual
import * as GitHub from ../../../github-client

class Query extends Component {
  static propTypes = {
    query: PropTypes.string.isRequired,variables: PropTypes.object,children: PropTypes.func.isRequired,normalize: PropTypes.func,}
  static defaultProps = {
    normalize: data => data,}
  static contextType = GitHub.Context

  state = {loaded: false,fetching: false,data: null,error: null}

  componentDidMount() {
    this._isMounted = true
    this.query()
  }

  componentDidUpdate(prevProps) {
    if (
      !isEqual(this.props.query,prevProps.query) ||
      !isEqual(this.props.variables,prevProps.variables)
    ) {
      this.query()
    }
  }

  componentWillUnmount() {
    this._isMounted = false
  }

  query() {
    this.setState({fetching: true})
    const client = this.context
    client
      .request(this.props.query,this.props.variables)
      .then(res =>
        this.safeSetState({
          data: this.props.normalize(res),error: null,loaded: true,fetching: false,}),)
      .catch(error =>
        this.safeSetState({
          error,data: null,loaded: false,)
  }

  safeSetState(...args) {
    this._isMounted && this.setState(...args)
  }

  render() {
    return this.props.children(this.state)
  }
}

export default Query

?

Conver props:

 // From 
static propTypes = {
    query: PropTypes.string.isRequired,}

// To:

function Query ({query,variables,children,normalize = data => data}) {

}

?

Conver Context:

// From
static contextType = GitHub.Context
...
const client = this.context

// To:
import {useContext} from react

function Query ({query,normalize = data => data}) {
  const clinet = useContext(GitHub.Context)
}

?

Conver State:

I don‘t like to cover each state prop to ‘useState‘ style,it is lots of DRY,instead,using useReducer is a better & clean apporach.

// From
state = {loaded: false,error: null}

//To:
  import {useContext,useReducer} from react
  ...
  const [state,setState] = useReducer(
    (state,newState) => ({...state,...newState}),defaultState)

?

Conver side effect:

// From:
  componentDidMount() {
    this._isMounted = true
    this.query()
  }

  componentDidUpdate(prevProps) {
    if (
      !isEqual(this.props.query,)
  }

// To:

  useEffect(() => {
    setState({fetching: true})
    client
      .request(query,variables)
      .then(res =>
        setState({
          data: normalize(res),)
      .catch(error =>
        setState({
          error,)
  },[query,variables]) // trigger the effects when ‘query‘ or ‘variables‘ changes  

?

Conver render:

// From:
  render() {
    return this.props.children(this.state)
  }

// To:
function Query({children ... }) {

 ...
 return children(state);    
}

?

-----

?

Full Code:

import {useContext,useReducer,useEffect} from react
import PropTypes from prop-types
import isEqual from lodash/isEqual
import * as GitHub from ../../../github-client

function Query ({query,normalize = data => data}) {
  const client = useContext(GitHub.Context)
  const defaultState = {loaded: false,error: null}
  const [state,defaultState)
  useEffect(() => {
    setState({fetching: true})
    client
      .request(query,variables]) // trigger the effects when ‘query‘ or ‘variables‘ changes
  return children(state)
}

export default Query

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读