我刚开始在React中使用Typescript。我尝试将其与React useReducer挂钩一起使用,但是由于一个奇怪的错误而卡住了。
这是我的代码:
Field f = obj.getClass().getDeclaredField("AssName"); //NoSuchFieldException
f.setAccessible(true);
String assignmentName = (String) f.get(obj);
当我将鼠标悬停在 export interface ContractObj {
company: string;
negotiationRenewalDate: string;
periodEnd: string;
periodStart: string;
scheduleForRenewal: boolean;
contractId: string;
}
type State = {
loading: boolean;
error: boolean;
contractsData: ContractObj[];
};
type Action =
| { type: 'FETCH_SUCCESS'; payload: ContractObj[] }
| { type: 'FETCH_ERROR'; payload: null };
const initialState: State = {
loading: true,
error: false,
contractsData: []
};
const reducer = (state: State, action: Action) => {
switch (action.type) {
case 'FETCH_SUCCESS':
return {
loading: false,
error: false,
contractsData: action.payload
};
case 'FETCH_ERROR':
return {
loading: false,
error: true
};
default: {
return state;
}
}
};
export const Contracts: React.FC<Props> = () => {
const [state, dispatch] = useReducer(reducer, initialState);
上时,这给我一个错误,即类型'State'的参数不能分配给'never'类型的参数
答案 0 :(得分:1)
确保始终在State
函数中返回相同的reducer
类型。如果将鼠标悬停在reducer
上,则会看到它当前具有以下签名:
const reducer: (state: State, action: Action) => State | {loading: boolean; error: boolean;}
那是因为在case 'FETCH_ERROR'
中遗漏了contractsData
,State
在reducer
中被定义为必填属性。通过向const reducer = (state: State, action: Action): State => { ... }
函数添加显式返回类型,可以轻松解决该问题:
contractsData
,您会得到(在这种情况下令人满意!)编译错误,抱怨缺少属性。最后,您可以在'FETCH_ERROR'
的情况下添加一个空的State
数组,或者在switch (action.type) {
case 'FETCH_ERROR':
return {
loading: false,
error: true,
contractsData: []
}
}
类型中将该属性定义为可选。
解决方案1:
type State = {
loading: boolean;
error: boolean;
contractsData?: ContractObj[];
};
解决方案2:
class _MyHomePageState extends State<MyHomePage> {
Ads appAds;
final String appId = Platform.isAndroid
? 'ca-app-pub-9010870803829618~619xxxxxxx'
: 'ca-app-pub-9010870803829618~390xxxxxxx';
final String bannerUnitId = Platform.isAndroid
? 'ca-app-pub-9010870803829618/936xxxxxx'
: 'ca-app-pub-9010870803829618/83xxxxxxx';
...
var eventListener = (MobileAdEvent event) {
if (event == MobileAdEvent.opened) {
print("The opened ad is clicked on.");
}
};
appAds = Ads(
appId,
bannerUnitId: bannerUnitId,
screenUnitId: screenUnitId,
listener: eventListener,
);
...
appAds.setBannerAd(
adUnitId: bannerUnitId,
size: AdSize.fullBanner,
anchorType: AnchorType.bottom,
anchorOffset: 50.0,
);