zoukankan      html  css  js  c++  java
  • [React] Cleaning up Functional Components with Custom Hooks

    In this lesson we take all of the hooks and logic from our <ExchangeRate> component and put them into a custom hook called useCurrencyCodes().

    What's the difference between a custom hook and a function we can use to organize our logic? Not much, really. Because custom hooks usually execute other hooks, they cannot be called conditionally (meaning we can't say if (ready) useCustomHook()). They must be called in the component's function body or in another custom hook. Redux hooks and React's built-in hooks are both included in our custom hook and work seamlessly together.

    Not only is it convenient to organize your logic in custom hooks, it makes them more sharable and testable as well. I don't recommend putting all of your logic into one large hook, but instead, consider where it would make your component easier to read by combining related hooks and logic into their own function.

    For more details about this pattern please check out this article from the React docs: https://reactjs.org/docs/hooks-custom.html

    Old:

    import React from "react";
    import PropTypes from "prop-types";
    import { connect } from "react-redux";
    import { ratesUpdated } from "../store/actions/RateActions";
    import {
      getCurrencyCode,
      getSupportedCurrencies,
    } from "../store/reducers/RateReducer";
    import { RateTableContainer } from "./RateTable";
    import { CurrencyCodePickerContainer } from "./CurrencyCodePicker";
    import { getExchangeRates } from "../api";
    import { AmountFieldContainer } from "./AmountField";
    
    export class ExchangeRate extends React.Component {
      constructor(props) {
        super(props);
        this.getLatestExchangeRates();
      }
      componentDidUpdate(prevProps) {
        if (this.props.currencyCode !== prevProps.currencyCode) {
          this.getLatestExchangeRates();
        }
      }
      getLatestExchangeRates() {
        const { currencyCode, updateRates, supportedCurrencies } = this.props;
        getExchangeRates(currencyCode, supportedCurrencies).then((rates) => {
          updateRates(rates);
        });
      }
      render() {
        return (
          <>
            <section>
              <h1 className="ExchangeRate-header">
                Exchange Rates <CurrencyCodePickerContainer />
              </h1>
            </section>
            <section>
              <AmountFieldContainer />
            </section>
            <section>
              <RateTableContainer />
            </section>
          </>
        );
      }
    }
    
    // props types
    ExchangeRate.propTypes = {
      updateCurrencyCode: PropTypes.func,
      currencyCode: PropTypes.string,
      supportedCurrencies: PropTypes.arrayOf(PropTypes.string),
    };
    
    // redux stuff
    function mapStateToProps(state) {
      return {
        supportedCurrencies: getSupportedCurrencies(state),
        currencyCode: getCurrencyCode(state),
      };
    }
    function mapDispatchToProps(dispatch) {
      return {
        updateRates: (rates) => dispatch(ratesUpdated(rates)),
      };
    }
    export const ExchangeRateContainer = connect(
      mapStateToProps,
      mapDispatchToProps
    )(ExchangeRate);

    New:

    import React, { useEffect } from "react";
    import { useSelector, useDispatch } from "react-redux";
    import { ratesUpdated } from "../store/actions/RateActions";
    import {
      getCurrencyCode,
      getSupportedCurrencies,
    } from "../store/reducers/RateReducer";
    import { RateTable } from "./RateTable";
    import { CurrencyCodePicker } from "./CurrencyCodePicker";
    import { getExchangeRates } from "../api";
    import { AmountField } from "./AmountField";
    
    export function ExchangeRate() {
      useCurrencyCodes();
      return (
        <>
          <section>
            <h1 className="ExchangeRate-header">
              Exchange Rates <CurrencyCodePicker />
            </h1>
          </section>
          <section>
            <AmountField />
          </section>
          <section>
            <RateTable />
          </section>
        </>
      );
    }
    
    function useCurrencyCodes() {
      const dispatch = useDispatch();
      const supportedCurrencies = useSelector(getSupportedCurrencies);
      const currencyCode = useSelector(getCurrencyCode);
      const updateRates = (rates) => dispatch(ratesUpdated(rates));
      useEffect(() => {
        getLatestExchangeRates();
      }, [currencyCode]);
      function getLatestExchangeRates() {
        getExchangeRates(currencyCode, supportedCurrencies).then((rates) => {
          updateRates(rates);
        });
      }
    }
  • 相关阅读:
    VBOX虚拟化工具做VPA学习都很方便硬件信息完全实现真实模拟
    Dynamics CRM2016 使用web api来创建注释时的注意事项
    Dynamics CRM build numbers
    域控制器的角色转移
    辅域控制器的安装方法
    利用QrCode.Net生成二维码 asp.net mvc c#
    给现有的word和pdf加水印
    利用LogParser将IIS日志插入到数据库
    短文本情感分析
    Dynamics CRM Ribbon WorkBench 当ValueRule的值为空时的设置
  • 原文地址:https://www.cnblogs.com/Answer1215/p/15253016.html
Copyright © 2011-2022 走看看