DEV Community

Discussion on: Simplify condition rendering in React.js

Collapse
 
miketalbot profile image
Mike Talbot ⭐ • Edited

Nice, I do something similar - it's also cool to add then and else as props. I also do this with switch:

import React, { useContext, useState } from "react"

const SwitchContext = React.createContext()

function ensureArray(ar) {
    return Array.isArray(ar) ? ar:[ar].filter((f) => f!==undefined)
}

function noop() {}

export function Switch({ value, children }) {
    const [switchContext] = useState({ cases: {} })
    switchContext.value = value
    return <SwitchContext.Provider value={switchContext}>{children}</SwitchContext.Provider>
}


export function Case({ when, children, execute = noop }) {
    const toCheck = ensureArray(when)
    const { value, cases } = useContext(SwitchContext)
    let condition = toCheck.some((when) => {
        if (typeof when === "function") {
            return when(value)
        } else {
            return when === value
        }
    })

    cases["" + when] = condition
    if (condition) {
        execute()
        return <>{children}</>
    } else {
        return null
    }
}

export function CaseElse({ children }) {
    const { cases } = useContext(SwitchContext)
    if (!Object.values(cases).some((v) => !!v)) {
        return <>{children}</>
    }
    return null
}

Enter fullscreen mode Exit fullscreen mode

I use it like this:

 <Switch value={column.type}>
            <Case when="action">
                <TableCell className={classes.tight} onClick={prevent(noop)}>
                    <LoadedAction column={column} item={item} />
                </TableCell>
            </Case>
            <Case when={["more", "than", "one", "reason", ()=>column.name === "including this!"]}>
                   {/* Some other cell */}
            </Case>
            {/* Other cases */}
            <CaseElse>
                <TableCell className={classes.tight}>
                    <LoadedColumn column={column} item={item} />
                </TableCell>
            </CaseElse>
</Switch>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
rmurati profile image
Redžep Murati

Oh wow this looks interesting. Thank you for sharing :)

Collapse
 
lonlilokli profile image
Lonli-Lokli

Nice, but you are missing Default case when no other matches

Collapse
 
miketalbot profile image
Mike Talbot ⭐ • Edited

Nope, I just called it CaseElse (my project has a ton of things called DefaultXYZ so it doesn't scan well).

Collapse
 
lonlilokli profile image
Lonli-Lokli

I've tried it, it's pretty neat but do you know how to limit type with React context? Ie to make Typescript do not complain about missing props

stackblitz.com/edit/react-ts-6ynx8...

Collapse
 
miketalbot profile image
Mike Talbot ⭐

I tried the link but didn't see any lint issues etc, what is it complaining about?