React-无法获得存储状态以传递子类组件

问题描述

我正在分派一个操作来在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来获取渲染时的数据,但目前,上述情况仍然有效