问题描述
我正在分派一个操作来在UserEditDialog FunctionComponent中重新创建userForEdit
状态变量,以便可以通过组件中的useSelector来使用它。因为我想将其传递给子类组件UserEditForm
。
这是UserEditDialog的代码
import {useAppdispatch} from "./../../../../../../redux/store";
interface UserEditDialogProps{
id: string;
show: boolean;
onHide: () => void;
}
export const UserEditDialog : React.FunctionComponent<UserEditDialogProps> = ({
id,show,onHide,}) => {
// Users UI Context
const dispatch = useAppdispatch();
// Where useAppdispatch is exported from store.ts as with "@reduxjs/toolkit";
// export type Appdispatch = typeof store.dispatch;
// export const useAppdispatch = () => usedispatch<Appdispatch>();
useEffect(() => {
// server call for getting User by id
dispatch<any>(actions.fetchUser(id)); //should we add .then callback?
},[id,dispatch]);
// Users Redux state
const { actionsLoading,userForEdit } = useSelector(
(state: RootState) => ({
actionsLoading: state.users.actionsLoading,userForEdit: state.users.userForEdit,}),shallowEqual
);
// server request for saving user
const saveUser = async (user: User) => {
if (!id) {
// server request for creating user
await dispatch<any>(actions.createuser(user));//.then(() => onHide());
onHide();
} else {
// server request for updating user
await dispatch<any>(actions.updateUser(user));//.then(() => onHide());
onHide();
}
};
return (
<Modal
size="lg"
show={show}
onHide={onHide}
aria-labelledby="example-modal-sizes-title-lg"
>
<UserEditDialogHeader _title="Edit User" />
<UserEditForm
saveUser={saveUser}
actionsLoading={actionsLoading}
user={userForEdit}
onHide={onHide}
/>
</Modal>
);
}
这是UserEditForm组件
interface UserEditFormProps{
saveUser:any,//(fileName:Blob) => Promise<void>,// callback taking a string and then dispatching a store actions
user:User,actionsLoading:boolean,onHide:() => void,}
interface UserEditFormState{
name: string,cardNo: string,faceFileInput:React.RefObject<any>,groups:any,groupName: string
}
export class UserEditForm extends React.Component<UserEditFormProps,UserEditFormState> {
// state: UserImportFormState;
constructor(props:UserEditFormProps){
super(props);
//this.loadUsers=props.loadUsers;
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.state={
name: props.user.name,//undefined user on props
cardNo:props.user.cardNo,//undefined user on props
faceFileInput: React.createRef(),// this should be a dropdown if there are groups or hide if no groups are there
groups:[{id:"abc",name:"ABC"},{id:"def",name:"DEF"},{id:"fgh",name:"FHG"}],groupName: props.user.groupName,//undefined user on props
}
}
//React.ChangeEvent<HTMLInputElement>
handleInputChange(event:React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) {
event.preventDefault();
const name = event.target.name;
// event.target.type
const value = event.target.value;
this.setState((current) => ({ ...current,[name]: value }))
}
handleSubmit(event:React.FormEvent<HTMLFormElement>) {
event.preventDefault();
const name:string=this.state.name;
const cardNo:string=this.state.cardNo;
const face:File=this.state.faceFileInput.current.files[0];
const groupName:string=this.state.groupName;
//construct updated user before submit
//if
// const user:User= {name,cardNo,face,groupName}
// this.props.saveUser(props.user.id,name,groupName);
}
render(){
return(
....
)}}
还有fetchUser操作
export const fetchUser = (id:string) => (dispatch:dispatch) => {
if (!id) {
return dispatch(actions.userFetched({ userForEdit: undefined }));
}
dispatch(actions.startCall({ callType: callTypes.action }));
return requestFromServer
.getUserById(id)
.then(response => {
const user = response.data;
dispatch(actions.userFetched({ userForEdit: user }));
})
.catch(error => {
error.clientMessage = "Can't find user";
dispatch(actions.catchError({ error,callType: callTypes.action }));
});
};
当我调试代码时,在组成子组件UserEditForm之前,没有分派UserEditDialog组件中的问题dispatch<any>(actions.fetchUser(id));
。原因可能是,useEffect是异步的。但是如何在组成子组件之前调度操作并获取最新的存储状态。将类组件用作FunctionComponent的子代有什么问题吗?
请帮忙!
解决方法
可以通过在未将userForEdit变量定义为时添加一个大小写来解决问题
//
if(!userForEdit){
return null;
}
return (
<Modal
size="lg"
show={show}
onHide={onHide}
aria-labelledby="example-modal-sizes-title-lg"
>
<UserEditDialogHeader id={id} />
{/* <Suspense fallback={<LayoutSplashScreen/>}> */}
<UserEditForm
saveUser={saveUser}
actionsLoading={actionsLoading}
user={userForEdit || usersUIProps.initUser}
onHide={onHide}
/>
{/* </Suspense> */}
</Modal>
);
解决该问题的正确方法是使用Suspense来获取渲染时的数据,但目前,上述情况仍然有效