Skip to content

IO Monad in React App #25

@MalQaniss

Description

@MalQaniss

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions