reactjs - useReducer() 正在为一个组件返回数据,而对于另一个组件,它正在返回 initialState
问题描述
实际上,我有 2 个组件需要来自具有某种状态的减速器的数据。该CurrentWeather
组件以非常高的水平和CurrentWeatherDetailed
详细的方式显示天气。第一个首先渲染,如果单击 Details 它将渲染CurrentWeatherDetailed
。CurrentWeather
调度一个动作来获取一些数据并使用该数据更新状态,稍后它通过 useReducer 获取状态并按预期呈现来自该状态的数据。另一方面,CurrentWeatherDetailed
, 也尝试获取当前填充的状态,但它只是返回null
(即initialState
)而不是实际处于状态的状态,考虑到CurrentWeather
,我假设;已经改变了状态。所以我尝试了很多,但我没有找到解释为什么会发生这种情况。
这是减速机:
export const initialState = {
loading: false,
error: null,
data: null,
}
const weatherRequestReducer = (state = initialState, action) => {
switch (action.type) {
case 'SEND':
return {...state,
loading: true,
error: null,
data: null,
};
case 'RESPONSE':
console.log(state);
console.log(action.responseData);
return {...state,
loading: false,
data: action.responseData
};
case 'ERROR':
return {...state,
loading: false,
error: action.errorMessage,
data: null
};
case 'CLEAR-ERROR':
return {...state,
error:null
};
default:
return state;
// throw new Error('Should not get there')
}
}
export default weatherRequestReducer;
这是一个使用 reducer 生成状态并将其返回给其他组件的钩子:
import {useReducer, useCallback, useState, useEffect} from 'react';
import weatherRequestReducer from "../reducers/weatherRequestReducer";
import {initialState} from "../reducers/weatherRequestReducer";
import api from '../utils/WeatherApiConfig'
const useCurrentWeather = () => {
const [weatherRequestState, dispatchWeatherRequestActions] = useReducer(weatherRequestReducer, initialState);
const sendRequestToGetCurrentWeather = useCallback(() => {
dispatchWeatherRequestActions({type: 'SEND'});
const uri = 'weather?q=London,uk';
api.get(uri)
.then(res => {
const responseData = res.data;
console.log(responseData.base);
dispatchWeatherRequestActions({type: 'RESPONSE', responseData: responseData});
})
.catch(err => {
console.log(err);
dispatchWeatherRequestActions({type: 'ERROR', errorMessage: 'Something went wrong!'});
});
}, []);
return {
getCurrentWeatherPointer: sendRequestToGetCurrentWeather,
isLoading: weatherRequestState.loading,
error: weatherRequestState.error,
data: weatherRequestState.data,
}
}
export default useCurrentWeather;
这是App
调用CurrentWeather
and的组件CurrentWeatherDetailed
,具体取决于虚拟状态:
import CurrentWeather from "./components/CurrentWeather/CurrentWeather";
import CurrentWeatherDetailed from "./components/CurrentWeather/CurrentWeatherDetailed";
import {useState} from "react";
import weatherRequestReducer from "./reducers/weatherRequestReducer";
function App() {
const [state, setState] = useState(0);
const renderComponent = () => {
setState(1)
}
let comp = <CurrentWeather renderComponent={renderComponent}/>;
if(state === 1){
comp = <CurrentWeatherDetailed/>
}
return {comp}
}
export default App;
以下组件工作正常console.log(data)
,显示了已要求的实际数据。
import React, {useEffect} from 'react';
import useCurrentWeather from "../../hooks/useCurrentWeather";
const CurrentWeather = (props) => {
const {getCurrentWeatherPointer, isLoading, error, data} = useCurrentWeather();
useEffect(() => {
getCurrentWeatherPointer();
}, [getCurrentWeatherPointer])
useEffect(() => {
console.log(data);
}, [data]);
const displayDetails = () => {
props.renderComponent();
}
return ( <Some JSX>
<div className={classes.buttonContainer}>
<button onClick={displayDetails}>Details →</button>
</div>
<Some JSX> );
}
export default CurrentWeather;
这是失败的组件,因为正在获取数据null
而不是组件已经获取的数据CurrentWeather
:
import React, {useEffect} from 'react';
import useCurrentWeather from "../../hooks/useCurrentWeather";
const CurrentWeatherDetailed = (props) => {
const {getCurrentWeatherPointer, isLoading, error, data} = useCurrentWeather();
useEffect(() => {
console.log(data)
setTimeout(() => {console.log(data);}, 500 );
}, [data])
return ( <Some JSX> );
}
export default CurrentWeatherDetailed;
如果我只是添加它可以正常工作useEffect(() => {getCurrentWeatherPointer();},[getCurrentWeatherPointer])
,但是,我不想这样做,因为我已经将它从 API 加载到 reducer 状态,所以再次加载它是没有意义的,但要使用已经存在的调用此详细组件时。CurrentWeatherDetailed
CurrentWeather
有谁知道为什么会这样?
提前谢谢各位。
解决方案
发生这种情况的原因是您一次只渲染一个组件,并且您的组件彼此是兄弟。当您的天气组件获取那里的数据时no weather details component
。因此,当您单击详细信息按钮时,您正在安装 CurrentWeatherDetailed,这意味着您正在从头开始创建组件。此时您CurrentWeatherDetailed
不知道发生了什么CurrentWeather
,因为组件彼此隔离,并且它们之间共享信息的唯一方法是通过 props 。所以你CurrentWeatherDetailed
再次初始化减速器。
您应该将您的 useReducer 移动到App
并将其从CurrentWeatherDetailed
and中删除CurrentWeather
。这样您就可以在CurrentWeatherDetailed
和之间共享信息CurrentWeather
。
function App() {
const [state, setState] = useState(0);
const {getCurrentWeatherPointer, isLoading, error, data} = useCurrentWeather();
const renderComponent = () => {
setState(1);
};
let comp = <CurrentWeather renderComponent={renderComponent} getCurrentWeatherPointer={getCurrentWeatherPointer}/>;
if (state === 1) {
comp = <CurrentWeatherDetailed data={data} />;
}
return {comp};
}
export default App;
推荐阅读
- javascript - Bootstrap 4 下拉菜单在数据表中不可见
- asp.net - Using SignalR via reflection
- iis - .Net Web api slow on server but fine locally
- python - Shifting Cells values in Python
- mysql - 在返回特定行的详细信息时对 sum() 进行 MySQL 查询
- mongodb - 数组中 ObjectId 的 $lookup 不起作用
- java - Apache POI SXSSF 在刷新行上显示 NullPointerException
- mysql - MySQL:删除基于 id 和其他列内容的所有记录
- linux - 在 Buster 上安装 Hyperion.ng - Raspberry Pi 4 (4 GB RAM) (Rev. 2020-02-13)
- c# - c# Generic vs Template in c++