getify / monio

The most powerful IO monad implementation in JS, possibly in any language!
http://monio.run
MIT License
1.05k stars 58 forks source link

IO Monad in React App #25

Open MalQaniss opened 2 years ago

MalQaniss commented 2 years ago

Hi Kyle, I am trying to use IO monad in React app(I don't know how much you are familiar with it), and I thought of using it as custom hook for every fetching side-effect needed in component. This is what I came up with so far:

import {useEffect, useState} from "react";
import {IO} from 'monio'

const useIO = ({sideEffectFunction, args}, dependencies = []) => {

    const [data, setData] = useState(null)

    function* main() {
        try {
            const returnVal = yield sideEffectFunction(...args)
            setData(returnVal)
        }catch (err){
            setData(err)
        }
    }

    useEffect(() => {
        IO.do(main).run()
    }, dependencies)

    return data

}

export default useIO;

And I can use it in some component to fetch some data like this:

import { isNotNil, logIf} from "./ContinentsSectionHelper";
import useIO from "../../hooks/useIO";
import {IO} from "monio";
import {chain, map, pipe, prop} from "ramda";

//Helpers
const sendRequestForContinent = continent => sendGetRequest(`https://corona.lmao.ninja/v3/covid-19/continents/${continent}?strict=true`)
const sendGetRequest = url => IO(() => fetch(url))
const checkResponse = response => response.ok? IO.of(response) : IO(() => {throw "Oops something is wrong with response"})
const getResponseJson = response => IO(() => response.json())

const fetchCountriesOfContinent = pipe(
    sendRequestForContinent, // send request
    chain(checkResponse), // check if response is OK
    chain(getResponseJson), // convert response to JSON
    map(prop('countries')), //get country property
)

//Component
const ContinentsSection = () => {

    const data = useIO({sideEffectFunction: fetchCountriesOfContinent, args:['europe']})

    logIf(data)(isNotNil)

    return (
        <section>
            <ContinentGraph />
        </section>
    )

}

export default ContinentsSection;

Would you say that this example is one possible solution to using monio in react, and would you implement it in some other way?