我具有以下功能组件。我进行了调试,并阅读了一些有关react-redux和useEffect的文章,但仍然没有成功。在初始渲染时,我的redux存储中的状态为null,但随后进行更改以反映数据的新状态。但是,我的react UI不能反映这一点。我了解问题所在,但我不知道该如何解决。我可能会以错误的方式做事,甚至无法从redux存储中的更新状态获取数据。
这是我的组成部分:
const Games = (props) => {
const [gamesData, setGamesData] = useState(null)
const [gameData, setGameData] = useState(null)
const [gameDate, setGameDate] = useState(new Date(2020, 2, 10))
const classes = GamesStyles()
// infinite render if placed in
// useEffect array
const {gamesProp} = props
useEffect(() => {
function requestGames() {
var date = parseDate(gameDate)
try {
props.getGames(`${date}`)
// prints null, even though state has changed
console.log(props.gamesProp)
setGamesData(props.gamesProp)
} catch (error) {
console.log(error)
}
}
requestGames()
}, [gameDate])
// data has not been loaded yet
if (gamesData == null) {
return (
<div>
<Spinner />
</div>
)
} else {
console.log(gamesData)
return (
<div><p>Data has been loaded<p><div>
{/* this is where i would change gameDate */}
)
}
}
const mapStateToProps = (state) => {
return {
gamesProp: state.gamesReducer.games,
}
}
const mapDispatchToProps = (dispatch) => {
return {
getGames: (url) => dispatch(actions.getGames(url)),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Games)
这是我的减速器
import {GET_GAMES} from '../actions/types'
const initialState = {
games: null // what we're fetching from backend
}
export default function(state = initialState, action){
switch(action.type){
case GET_GAMES:
// prints correct data from state
//console.log(action.payload)
return{
...state,
games: action.payload
}
default:
return state
}
}
这是我的行动
import axios from 'axios'
import {GET_GAMES} from './types'
// all our request go here
// GET GAMES
export const getGames = (date) => dispatch => {
//console.log('Date', date)
axios.get(`http://127.0.0.1:8000/games/${date}`)
.then(res => {
dispatch({
type: GET_GAMES,
payload: res.data
})
}).catch(err => console.log(err))
}
当我将状态中的道具放置在useEffect
的依存关系数组中时,状态会更新,但会导致无限渲染,因为道具正在更改。
即使我破坏了道具,也会发生这种情况。
这是在初始渲染器上更新后我的redux状态的图像。
答案 0 :(得分:1)
您遇到了问题,因为您试图根据closure中的数据来设置状态。即使父数据发生更改,useEffect中的props.gamesProp
也永远不会更新。
效果props.gamesProp
之所以为null的原因是因为在每个渲染中,您的组件本质上都有一个props的新实例,因此当useEffect运行时,useEffect的内部部分会看到的props版本是那个渲染器上存在的东西。
组件中的任何函数(包括事件处理程序和效果)都可以从其创建的渲染中“看到”道具和状态。
https://reactjs.org/docs/hooks-faq.html#why-am-i-seeing-stale-props-or-state-inside-my-function
除非您必须在组件中修改gamesState,否则我强烈建议您不要将prop复制到该状态。
我还建议使用useDispatch
和useSelector
代替功能组件的连接。
根据我当前所看到的内容以及我刚刚描述的内容,对您的组件进行了一些修改:
import { useDispatch, useSelector } from 'react-redux';
const Games = (props) => {
const gamesData = useSelector((state) => state.gamesReducer.games);
const dispatch = useDispatch();
const [gameData, setGameData] = useState(null);
const [gameDate, setGameDate] = useState(new Date(2020, 2, 10));
const classes = GamesStyles();
// infinite render if placed in
// useEffect array
useEffect(() => {
const date = parseDate(gameDate);
try {
dispatch(actions.getGames(`${date}`));
} catch (error) {
console.log(error);
}
}, [gameDate, dispatch]);
// data has not been loaded yet
if (gamesData == null) {
return (
<div>
<Spinner />
</div>
);
} else {
console.log(gamesData);
return (
<div>
<p>Data has been loaded</p>
</div>
// this is where i would change gameDate
);
}
};
export default Games;
如果您需要从道具中获取状态,这是钩子上的React文档必须说的:
https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-getderivedstatefromprops