我想使用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)
答案 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的直接替代,因为它的工作原理有所不同。由于最接近的时间与useLayoutEffect
和componentDidMount
匹配,因此最接近的实际上是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>
);
}