Home > Enterprise >  React Native: Typescript - data possibly undefined
React Native: Typescript - data possibly undefined

Time:06-04

I've got a some data being fetched using RTK Query. I load this data (array of objects) in a screen and then slice some portion of it.

It's more of a typescript question but I'll post the apiSlice:

interface Post {
  userId: number;
  id: number;
  title: string;
  body: string;
}

export const blogpostsApi = createApi({
  reducerPath: 'blogpostsApi',
  baseQuery: fetchBaseQuery({ baseUrl: 'http://localhost:3500' }),
  endpoints: builder => ({
    getBlogPosts: builder.query<Post[], void>({
      query: () => '/todos',
      transformResponse: (res: Post[], meta) => res.sort((a, b) => b.id - a.id),
    }),
  }),
});

The relevant excerpts from the screen:

const { data, isLoading } = useGetBlogPostsQuery();
const latestData = data?.slice(0, 10);
useEffect(() => {
    if (!isLoading && latestData.length > 0 && some_other_condition) {
    ... some code
    }
}, [latestData]);
useEffect(() => {
    if (!isLoading && latestData[0].id === 'something' && some_other_condition) {
    ... some code
    }
}, [latestData]);

As you can see, I've added the optional chaining operator to data?.slice... (as this is a recommended solution for that on SO, from what I have seen. But then typescript also underlines all the instances of latestData.length and latestData[0].id.

Now I know I could silence the typescript error by adding the optional chaining operator to all those instances as well but I'm wondering it that's really the best way of doing it for 2 reasons:

  1. Adding it to all the instances will unnecessarily increase the compiled code length
  2. The way I use latestData above in the two effects is in conditional statements to check if it exists/is defined so it is perfectly OK for it to be undefined.

So I guess my question is what would be the correct way to solve this error. Isn't adding the optional chaining operator just a quick and dirty hack to silence the error especially if it appears in conditional statements? I know I could also suppress the error by asking Webstorm to ignore it (as per the error screenshot below)
The error: enter image description here

CodePudding user response:

This is absolutely normal behaviour.

The optional chaining operator is not a Typescript thing, it's Javascript and it works like that:

myVar?.prop1?.prop2?.prop3

If myVar is undefined (or null), the rest of the code won't be evaluated and the whole expression will return undefined.

Then, if myVar is not undefined (or null), then the code will try to access the prop1 property of myVar.

Since there is a ? after prop1, it will repeat the same process until it finds undefined/null or after it reaches the end of the chain without finding any undefined/null.

It seems like you are confusing the Javascript ? operator with the Typescript ! non-null assertion.

If you only want to tell the compiler that you are confident about a variable being "non-null" (that also means non undefined), you can use the ! operator instead.

Like so:

const { data, isLoading } = useGetBlogPostsQuery();
const latestData = data!.slice(0, 10); // change this line here
useEffect(() => {
    if (!isLoading && latestData.length > 0 && some_other_condition) {
    ... some code
    }
}, [latestData]);
useEffect(() => {
    if (!isLoading && latestData[0].id > 0 && some_other_condition) {
    ... some code
    }
}, [latestData]);

However, you should really check manually if data is not undefined or null before using it. And that would even release you from having to use any assertion operator !

Like that:

const { data, isLoading } = useGetBlogPostsQuery();
if (!data){
  // do something to handle the problem
}
const latestData = data.slice(0, 10);
useEffect(() => {
    if (!isLoading && latestData.length > 0 && some_other_condition) {
    ... some code
    }
}, [latestData]);
useEffect(() => {
    if (!isLoading && latestData[0].id > 0 && some_other_condition) {
    ... some code
    }
}, [latestData]);
  • Related