reactjs - Argument av typ 'Promise' kan inte tilldelas till parameter av typen 'string'


Innan jag initierar en React-app hämtar jag användarens information från localStorage. Sedan, tack vare hans id, startar jag en socketanslutning med servern.

När man skickar användarens id till socket-funktionen, hävdar TypeScript att:

Argument av typen 'Promise' kan inte tilldelas en parameter av typen 'string'

Här är min index.tsx-fil:

const user = fetchUser();

if (user) {
  getNotifications(user);
}

ReactDOM.render(
      <App />,
  document.getElementById("root")
);

Och funktionen fetchUser():

export async function fetchUser() {
  try {
    if (!localStorage.getItem("MyAppName")) return null;
    const user = await jwt_decode(localStorage.MyAppName);
    updateUser(user);
    return user.id;
  } catch (err) {
    return null;
  }
}

Hur åtgärdar man detta? Om jag tar bort async/await fungerar det, men prestandamässigt, är det okej att blockera tråden så här innan appen initieras?

Svar #1

getUser returnerar ett promise precis som vilken funktion som helst som definieras med async, vilket du manipulerar innan det är löst. Eftersom du arbetar i ett modulgloalt scope kan du göra följande, vilket skulle köras på ett icke-blockerande sätt:

    getUser.then(user =>  {
       if(user) {
           getNotifications(user);
       }
    })
    .catch(e => console.log('Error: ', e))

Svar #2

Jag antar att din App tar emot notiser som en prop på något sätt. Vi vill ladda notiserna asynkront och tillåta App att rendera. När hämtningen är klar kommer props för App att ändras för att inkludera notiserna. Beroende på vad din app förväntar sig, kan du antingen skicka en tom array av notiser, eller så kan du också lägga till någon prop som fungerar som en flagga, till exempel isLoadingNotifications, så att du kan veta att du ska rendera en indikator inom appen istället för notiserna.

Allt detta bör göras inom en React-komponent. Förmodligen längre ner i trädet, men för nu låt oss bara omsluta din App med en OuterApp.

interface Notification {
  /**... */
}

const OuterApp = () => {

  const [notifications, setNotifications] = useState<Notification[]>([]);

  const loadNotifications = async () => {
    await fetchUser();
    if ( user ) {
      const notes = await getNotifications( user );
      setNotifications( notes );
    }
  }

  useEffect( () => {
     loadNotifications();
    // should probably have a cleanup
  }, [] );

  return (
    <App 
      notifications={notifications}
    />
  )

}

ReactDOM.render(
  <OuterApp />,
  document.getElementById("root")
);