GithubHelp home page GithubHelp logo

Conditional or Switch HOC? about recompose HOT 16 CLOSED

acdlite avatar acdlite commented on July 20, 2024 1
Conditional or Switch HOC?

from recompose.

Comments (16)

wuct avatar wuct commented on July 20, 2024 21

Base on the info in this thread, I propose we can add a new HOC, cond(), to Recompose, which signature is similar to ramda/cond:

[[(props → Boolean), HOC]] → HOC

Ex:

cond([
  [props => props.error, renderComponent(ErrorComponent)],
  [props => props.warning, renderComponent(WarningComponent)],
  [() => true, a => a]
])

from recompose.

bholloway avatar bholloway commented on July 20, 2024 5

@acdlite I think your resolution was good but there is definitely a place for a switch() that operates on HOC. Is there another issue that attends to this?

I would like to handle 4 cases for a prop:

missing | instanceof Error | empty List | default (non-empty list)

Currently I need to compose 3 x branch HOCs to do this.

from recompose.

wuct avatar wuct commented on July 20, 2024 2

And IMO we should let the consumer decide how to compose their HOC, instead of wrapping renderComponent for them.

from recompose.

wuct avatar wuct commented on July 20, 2024 1

@timkindberg They're similar. However, cond is familiar to ramda users :)

from recompose.

wuct avatar wuct commented on July 20, 2024 1

@barbalex No, it hasn't been added.

from recompose.

lucasfcosta avatar lucasfcosta commented on July 20, 2024 1

I also think it would be very useful and I'm happy to implement it if needed.

from recompose.

acdlite avatar acdlite commented on July 20, 2024

Thanks for your suggestions! I'm hesitant to add a conditional() helper because it's not clear from the name how it's different from branch(). However, I've been thinking about adding a renderComponent() helper, which is really just the identity function with a more meaningful name This isn't quite true, clarification below. With this helper, you could achieve the same effect as conditional() like so:

const Component = branch(
  test,
  renderComponent(Foo), // Foo is rendered if true
  renderComponent(Bar) // Bar is rendered if false
)(BaseComponent)

This involves a bit more typing, but it avoids the confusion of whether branch() accepts an HoC or a component. I'm open to also adding your proposed conditional() helper if you can think of a better name for it.

Your switch() idea is also neat, but again, I would want it to operate on HoCs, not components.

EDIT:

renderComponent() would look like this:

const renderComponent = Component => () => Component;

For stateless function components—but not class components—you could replace this with the identity function.

from recompose.

acdlite avatar acdlite commented on July 20, 2024

I've added renderComponent() to version 0.5.0. There's an example of how to use it here: https://github.com/acdlite/recompose/blob/master/docs/API.md#rendercomponent

from recompose.

smeijer avatar smeijer commented on July 20, 2024

Having the same "issue" as @bholloway. I need to render an Avatar based on either:

userId: fetch user from api
user: should contain all info
picture: render simple image
anonymous: show guest icon

<Avatar userId="u1" />
<Avatar user={{ picture: '...' }} />
<Avatar picture="http://....." />
<Avatar />

from recompose.

smeijer avatar smeijer commented on July 20, 2024

The cond would be awesome.

from recompose.

timkindberg avatar timkindberg commented on July 20, 2024

I wonder how similar this is to a helper I wrote called nonOptimalStates?

https://github.com/timkindberg/egghead-recompose/blob/master/08-Replace-a-Component-with-Non-Optimal-States-Using-Recompose/index.jsx#L52

from recompose.

barbalex avatar barbalex commented on July 20, 2024

has cond (#21 (comment)) been added?

It is not documented: https://github.com/acdlite/recompose/blob/master/docs/API.md

from recompose.

orenklein avatar orenklein commented on July 20, 2024

Even though it has been awhile and in most cases it is recommended to use switch (#386 (comment)), in case you actually want to use a switch as an HOC -
(The definition is based on #21 (comment) and the implementation is mostly inspired by branch implementation)

import { Component, ComponentType, createFactory } from 'react';
import { ComponentEnhancer, InferableComponentEnhancer, setDisplayName, wrapDisplayName } from 'recompose';

type mapper<TInner, TOuter> = (input: TInner) => TOuter;
type predicate<T> = mapper<T, boolean>;
type Condition<TOuter> = [predicate<TOuter>, ComponentEnhancer<any, any> | InferableComponentEnhancer<{}>];

const identity = Component => Component;

export function cond<TOuter = any>(conditions: Array<Condition<TOuter>>): ComponentEnhancer<any, TOuter> {
  return (BaseComponent: ComponentType<any>) => {
    const factories = Array(conditions.length);
    class Cond extends Component<TOuter> {
      render() {
        const enhancerIndex = conditions.findIndex(([test, hoc]) => test(this.props));
        const enhancer = enhancerIndex > -1 ? conditions[enhancerIndex][1] : identity;
        factories[enhancerIndex] = factories[enhancerIndex] || createFactory(enhancer(BaseComponent));
        return factories[enhancerIndex](this.props);
      }
    }
    if (process.env.NODE_ENV !== 'production') {
      return setDisplayName<TOuter>(wrapDisplayName(BaseComponent, 'cond'))(Cond);
    }
    return Cond;
  };
}

from recompose.

Startouf avatar Startouf commented on July 20, 2024

@wuct @arturmuller this issue was closed, maybe reopen it, or open a new one with the cond proposal ?

from recompose.

kohlmannj avatar kohlmannj commented on July 20, 2024

Here's how I've ended up using branch() wrapped around a "null" component:

export default branch(
  props => !!canRenderBaseComponent(props),
  renderComponent(BaseComponent),
  renderNothing
)(() => null);

from recompose.

futpib avatar futpib commented on July 20, 2024

Had to reinvent this just now, called it branches to avoid import name clash with cond from ramda.

import {
	reduceRight,
} from 'ramda';

import {
	branch,
	renderNothing,
} from 'recompose';

export const branches = reduceRight(([ test, left ], right) => branch(test, left, right), renderNothing);

Usage example:

import {
	prop,
	T as alwaysTrue,
} from 'ramda';

import {
	compose,
	renderNothing,
	renderComponent,
} from 'recompose';

import { branches } from '../../utils/branches';

const UserDetails = () => 'UserDetails';
const TransactionDetails = () => 'TransactionDetails';
const OverallDetails = () => 'OverallDetails';

export const Details = compose(
	/* ... */
	branches([
		[ prop('selectedUserId'), renderComponent(UserDetails) ],
		[ prop('selectedTransactionId'), renderComponent(TransactionDetails) ],
		[ alwaysTrue, renderComponent(OverallDetails) ],
	])
)(renderNothing);

from recompose.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.