如何使用useEffect替换componentDidMount?

时间:2020-10-12 03:33:21

标签: javascript reactjs react-router

我想使用useEffect()来代替componentWillMount(),但是我发现该钩子不能在类组件中使用,因此我将代码更改为Function组件,但是这样做会导致更多错误整个组件,带有this.xxx的所有代码都出现错误,如何编辑以下代码以使其正常工作?请帮我。下面的代码可以与componentWillMount()正常工作。

import React, { Component } from 'react';
import './index.less';
import { formateDate } from '../../utils/dateUtils';
import memoryUtils from '../../utils/memoryUtils';
import { reqWeather } from '../../api/index';
import { withRouter } from 'react-router-dom';
import menuList from '../../config/menuConfig';

class Header extends Component {
  state = {
    currentTime: formateDate(Date.now()),
    dayPictureUrl: '',
    weather: '',
  };
  getTime = () => {
    setInterval(() => {
      const currentTime = formateDate(Date.now());
      this.setState({ currentTime });
    }, 1000);
  };
  getWeather = async () => {
    const { dayPictureUrl, weather } = await reqWeather('Auckland');
    this.setState({ dayPictureUrl, weather });
  };
  getTitle = (props) => { 
    const path = this.props.location.pathname;
    let title;
    menuList.forEach(item => {
      if (item.key === path) {
        title = item.title;
      } else if (item.children) {
        const cItem = item.children.find(cItem => cItem.key === path);
        if (cItem) {
          title = cItem.title;
        }
      }
    });
    return title;
  };
  componentDidMount() {
    this.getTime();
    this.getWeather();
  }
  render() {
    const { currentTime, dayPictureUrl, weather } = this.state;
    const username = memoryUtils.user.username;
    const title = this.getTitle();
    return (
      <div className="header">
        <div className="header-top">
          <span>Welcome, {username}</span>
          <a href>logout</a>
        </div>
        <div className="header-bottom">
          <div className="header-bottom-left">{title}</div>
          <div className="header-bottom-right">
            <span>{currentTime}</span>
            <img src={dayPictureUrl} alt="weather" />
            <span>{weather}</span>
          </div>
        </div>
      </div>
    );
  }
}
export default withRouter(Header)

2 个答案:

答案 0 :(得分:1)

我已经从react类转换为react钩子,希望对我有帮助,我没有经过测试,因为我没有所需的外部文件,但希望对其他解决方案有所帮助;)

import React, { useState, useEffect } from 'react';
import './index.less';
import { formateDate } from '../../utils/dateUtils';
import memoryUtils from '../../utils/memoryUtils';
import { reqWeather } from '../../api/index';
import { withRouter, useLocation } from 'react-router-dom';
import menuList from '../../config/menuConfig';



function Header(){
const [currentTime, setCurrentTime] = useState(formateDate(Date.now()))
const [dayPictureUrl, setDayPictureUrl] = useState('')
const [weather, setWeather] = useState('')
const location = useLocation();
const path = location.pathname;

useEffect(() => {
    getTime();
    getWeather();
},[]);


const getTime = () => {
    setInterval(() => {
      const currentTime = formateDate(Date.now());
      setCurrentTime(currentTime)
    }, 1000);
  };
const   getWeather = async () => {
    const { dayPictureUrl, weather } = await reqWeather('Auckland');
    setDayPictureUrl(dayPictureUrl)
    setWeather(weather)

  };
const  getTitle = (props) => { 
    let title;
    menuList.forEach(item => {
      if (item.key === path) {
        title = item.title;
      } else if (item.children) {
        const cItem = item.children.find(cItem => cItem.key === path);
        if (cItem) {
          title = cItem.title;
        }
      }
    });
    return title;
  };
  const username = memoryUtils.user.username;
  const title = getTitle();
  return (<div className="header">
  <div className="header-top">
    <span>Welcome, {username}</span>
    <a href>logout</a>
  </div>
  <div className="header-bottom">
    <div className="header-bottom-left">{title}</div>
    <div className="header-bottom-right">
      <span>{currentTime}</span>
      <img src={dayPictureUrl} alt="weather" />
      <span>{weather}</span>
    </div>
  </div>
</div>  )
}


export default Header

答案 1 :(得分:0)

这是我将函数转换为使用钩子的方法。

关于钩子的最好的事情之一就是它们可以被任意多次调用,这使我们能够将组件的关注点分离为逻辑块。

useEffect不应被视为componentDidMount的直接替代,因为它的工作原理有所不同。由于最接近的时间与useLayoutEffectcomponentDidMount匹配,因此最接近的实际上是componentdDidUpdate。有关两者之间区别的更多详细信息:useEffect vs useLayoutEffect。尽管通常应该主要使用useEffect

习惯使用钩子需要您对组件的看法进行一些转变,但是在我看来,值得努力!

import React, {useEffect, useMemo, useState} from 'react';
import './index.less';
import { formateDate } from '../../utils/dateUtils';
import memoryUtils from '../../utils/memoryUtils';
import { reqWeather } from '../../api/index';
import { useLocation } from 'react-router-dom';
import menuList from '../../config/menuConfig';

export default function Header (props){
  const [currentTime, setCurrentTime] = useState(formateDate(Date.now()));
  useEffect(()=>{
    const intervalId = setInterval(()=>{
      setCurrentTime(formateDate(Date.now()));
    },1000)
    // Make sure to cleanup your effects!
    return ()=>{clearInterval(intervalId)}
  },[])

  const [dayPictureUrl, setDayPictureUrl] = useState('');
  const [weather, setWeather] = useState('');
  useEffect(() => {
    const getWeather = async () => {
      const { dayPictureUrl, weather } = await reqWeather('auckland');
      setDayPictureUrl(dayPictureUrl);
      setWeather(weather);
    };
    // Assuming that we want to have the weather dynamically based on a passed in prop (i.e. props.city), or a state.
    getWeather();
  }, []);

  // useLocation gets the location via a hook from react router dom
  const location = useLocation();
  const title = useMemo(()=>{
    // useMemo as this can be an expensive calculation depending on the length of menuList
    // menuList is always a constant value, so it won't change
    const path = location.pathname;
    let title;
    menuList.forEach(item => {
      if (item.key === path) {
        title = item.title;
      } else if (item.children) {
        const cItem = item.children.find(cItem => cItem.key === path);
        if (cItem) {
          title = cItem.title;
        }
      }
    });
    return title;
  },[location.pathname])
  
  const username = memoryUtils.user.username;

  return (
    <div className="header">
      <div className="header-top">
        <span>Welcome, {username}</span>
        <a href>logout</a>
      </div>
      <div className="header-bottom">
        <div className="header-bottom-left">{title}</div>
        <div className="header-bottom-right">
          <span>{currentTime}</span>
          <img src={dayPictureUrl} alt="weather" />
          <span>{weather}</span>
        </div>
      </div>
    </div>
  );
}