1

Can anyone please explain me what const rerender = React.useState(0)[1] is this?

import React from 'react'
import axios from 'axios'
import {
  useQuery,
  useQueryClient,
  QueryClient,
  QueryClientProvider,
} from "@tanstack/react-query"
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"

const getCharacters = async () => {
  await new Promise((r) => setTimeout(r, 500))
  const { data } = await axios.get('https://rickandmortyapi.com/api/character/')
  return data
}

const getCharacter = async (selectedChar) => {
  await new Promise((r) => setTimeout(r, 500))
  const { data } = await axios.get(
    `https://rickandmortyapi.com/api/character/${selectedChar}`,
  )
  return data
}

const queryClient = new QueryClient()

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Example />
    </QueryClientProvider>
  )
}

function Example() {
  const queryClient = useQueryClient()
  **const rerender = React.useState(0)[1]**
  const [selectedChar, setSelectedChar] = React.useState(1)

  const charactersQuery = useQuery(['characters'], getCharacters)

  const characterQuery = useQuery(['character', selectedChar], () =>
    getCharacter(selectedChar),
  )

  return (
    <div className="App">
      <p>
        Hovering over a character will prefetch it, and when it's been
        prefetched it will turn <strong>bold</strong>. Clicking on a prefetched
        character will show their stats below immediately.
      </p>
      <h2>Characters</h2>
      {charactersQuery.isLoading ? (
        'Loading...'
      ) : (
        <>
          <ul>
            {charactersQuery.data?.results.map((char) => (
              <li
                key={char.id}
                onClick={() => {
                  setSelectedChar(char.id)
                }}
                onMouseEnter={async () => {
                  await queryClient.prefetchQuery(
                    ['character', char.id],
                    () => getCharacter(char.id),
                    {
                      staleTime: 10 * 1000, // only prefetch if older than 10 seconds
                    },
                  )

                  setTimeout(() => {
                    **rerender({})**
                  }, 1)
                }}
              >
                <div
                  style={
                    queryClient.getQueryData(['character', char.id])
                      ? {
                          fontWeight: 'bold',
                        }
                      : {}
                  }
                >
                  {char.id} - {char.name}
                </div>
              </li>
            ))}
          </ul>

          <h3>Selected Character</h3>
          {characterQuery.isLoading ? (
            'Loading...'
          ) : (
            <>
              <pre>{JSON.stringify(characterQuery.data, null, 2)}</pre>
            </>
          )}
          <ReactQueryDevtools initialIsOpen />
        </>
      )}
    </div>
  )
}

I want to know what it means, i am unable to understand this useState syntax I never seen this type of syntax. Can anyone share something about this?

Vijay Sai
  • 15
  • 4
  • It just looks like it's accessing the first element of the array returned, with no access to the setter, – Azzy Nov 14 '22 at 06:55

1 Answers1

5

useState has two parts the value and a function to update the value.

Take a look at the below snippet which explains how the useState hook is assigning values normally.

  var fruitStateVariable = useState('banana'); // Returns a pair
  var fruit = fruitStateVariable[0]; // The value of the state
  var setFruit = fruitStateVariable[1]; // A asynchronous function to update the state.

By accessing the item with index 1 you are assigning rerender a function to update the state, which will trigger a rerender, as React sees the value going from 0 -> {}.

As to why the code is doing this, it seems the author is trying to get around useState being asynchronous to update. This is not a good pattern and should be avoided!. As you rightly have said you have not seen this syntax before, because it is not an appropriate way of triggering a function to rerender.

React Docs recommends this way if you really need to force the retrigger:

const forceUpdate = useReducer(x => x + 1, 0)[1] 

But a key line from this resource is to Try to avoid this pattern if possible.

DanielJ
  • 729
  • 2
  • 7
  • 26