Conditionals and Index Mondads

I am using the react-basic-hooks library and am trying to conditionally return a Render monad (which uses the IxMonad typeclass). However I can’t figure out how to do this because the different cases have different state shapes.
What I have so far is this:

forall a hooks h . QueryState a -> (a -> React.Render Unit hooks JSX) -> React.Render Unit h JSX
handleState (Loading) fn = pure $ <SOME JSX>
handleState (Error e) fn = pure $ <SOME JSX>
handleState (Data d) fn = fn d

However that type signature is incorrect and so far I can’t find a way to write a function that is pure or some arbitrary render. Any ideas of how to go about this?

An invariant of hooks is that you must always use the same hooks in the same order across renders, which is what the indexed type variable is tracking. You are trying to conditionally use or not use hooks, which violates that invariant.

3 Likes

https://www.npmjs.com/package/react-loads-hook reaturns 3 stateful components, not jsx

import React from 'react';
import { useLoads } from 'react-loads';
 
export default function DogApp() {
  const getRandomDog = () => axios.get('https://dog.ceo/api/breeds/image/random');
  const { response, error, load, Pending, Resolved, Rejected } = useLoads(getRandomDog);
 
  return (
    <div>
      <Pending>
        <div>loading...</div>
      </Pending>
      <Resolved>
        <div>
          <div>
            {response && <img src={response.data.message} width="300px" alt="Dog" />}
          </div>
          <button onClick={load}>Load another</button>
        </div>
      </Resolved>
      <Rejected>
        <div type="danger">{error.message}</div>
      </Rejected>
      <Resolved or={[Pending, Rejected]}>
        This will show when the state is pending, resolved or rejected.
      </Resolved>
    </div>
  );
}