[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);
    });
  }
}
复制代码

 

posted @   Zhentiw  阅读(48)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2020-09-10 [CSS] Use CSS pseudo-elements and mix-blend-mode to Create a Duotone Style Effect
2020-09-10 [Machine Learning] Backpropagation Algorithm
2020-09-10 [Machine Learning] Neural Network: Cost Function
2015-09-10 [React] Intro to inline styles in React components
2015-09-10 [AngualrJS + Webpack] Production Source Maps
2015-09-10 [AngularJS + Webpack] Uglifying your JavaScript
点击右上角即可分享
微信分享提示