Documentation for React Application
stliang opened this issue · 3 comments
Is your feature request related to a problem? Please describe.
I am trying to use crocks for React App, to make a functional react component, I need to return JSX. If I want to return JSX based on an Either type, I can either detect if it is Right or Left, but if I need a value from Right, I am wrapped inside an Either type. Using bimap and put a return statement seems wrong. A use case for me is wrap an user object in Either. If the user is login I use Right(user) otherwise Left('anonymous'). Based on the user state, I want to return JSX or React Component in different way. Seems like I can not do that. I am started to think I can not use crocks with React.
I reviewed this example:
https://github.com/dbagia/declarative-form-generator
It maps some data to JSX, but does not involve ADT like Either or Maybe etc.
Describe the solution you'd like
I would like to have in the documentation where crocks should be used. It looks like a backend thing and can be use at the front end in a limited way.
Describe alternatives for how you do this now
N/A
Code
const loginButton = () => {
if (user) {
return (
<ListItem button onClick={logout}>
<ListItemIcon>
<Icon>lock</Icon>
</ListItemIcon>
<ListItemText
primary={"Logout"}
primaryTypographyProps={{ noWrap: true }}
/>
</ListItem>
)
} else {
return (
<ListItem button onClick={login}>
<ListItemIcon>
<Icon>lock_open</Icon>
</ListItemIcon>
<ListItemText
primary={"Login"}
primaryTypographyProps={{ noWrap: true }}
/>
</ListItem>
)
}
}
Additional context
Instead of if (user) {
, I tried to use Either type and bimap. But I don't think I should use return statement within the bimap.
This is a nice suggestion
If you'd like some advice for now i think you could look into doing it via pure function components, this is how i do it now. These are functions and work with the ADT's as normal functions do. You can then have whichever function creates the Either
or Maybe
and compose it with your functions to create components.
return compose(
option(<OtherComponent />)
map(createNormalComponent),
createMaybeFromProps
)
Another option is using the IfElse
helper to create the composed component by specifying the predicate and the two component functions
IfElse(IsLoaded, LoadingComponent, UserItem)
This feeds in to a more general set of requests to have a collection of tutorials and "Real World" scenarios
@stliang Where we work we use crocks
and other functional/ADT libs in both the front end and backend.
It really just depends on how you define the "edge" of your program. The edge being where all types are unwrapped and resolved to an answer.
For Sum types, like Either
, we have a function that will let you fold out your result. It is called either
and takes 2 functions. The first is called if the instance is in Left
, the second if Right
. either.
So you "could" use types like this for a simple if...then
. That function you provided has a siggy of Props -> Component
. So the real power is if you have function that work on the prop
that can then be transformed before calling render. So you can change the props
around conditionally before it hits the render. Like a mixin
or a limited HOC that just transforms props. so you can have something like.
// isAdmin :: Props -> Either _ Props
// modifyAdmin :: Props -> Props
// modifyUser :: Props -> Props
// normalizeProps:: Props -> Props
// render Admin :: Props -> Component
// renderUser :: Props -> Component
// renderThat :: Props -> Component
const renderThat = compose(
either(renderUser, renderAdmin),
bimap(modifyUser, modifyAdmin),
chain(isAdmin),
compose(Either.of, normalizeProps) // lift into a Right
)
This is all consolidated into one composition for examples sake, but this really should be (2) or three compositions composed into one.
Thanks for the advice, I believe this should work. Will test it out.