Comments (16)
@alfonsogarciacaro cool I'll draft a PR in the next few days. I can't really comment on the finer points yet but I'll go over the docs again and look at some usage, maybe I will have a bit more input then.
@forki it's a silly name but it what is used in the official react docs: https://reactjs.org/docs/higher-order-components.html. As such I would stay with higher order components as that is what people coming from react would be looking for and how third party components that follow this pattern would describe themselves.
from fable-react.
I added a first draft of the docs - please let me know what you think!
from fable-react.
Thanks a lot for your comments! Yes, so far we've tried to closely follow the React terminology to prevent mismatches with React documentation. We should keep the reference to HOC in this case here too.
from fable-react.
Hi @danyx23! You're right, we have the pieces to easily import React components but we're missing the guide to do it. There are currently two ways to do it:
- Dynamically: Just import the component and define the properties with a pojo. A mini-guide to do that can be found here.
- Creating bindings: If you plan to use the component a lot, it maybe worthy to write some bindings to use DUs for the props and get more idiomatic F#. We're missing a guide for it (maybe @Zaid-Ajaj was writing one) although you can check other bindings in this repo (like the one for Leaflet). The most important thing is to call
keyValueList
before passing the prop list to the imported component (as in here).
EDIT: @danyx23 documented how to use 3rd party React components. You can also see below an example of importing HOC components.
from fable-react.
Hi @alfonsogarciacaro, thank your for your reply! How do you suggest to go forward with this? Should I create a PR with an initial draft of a documentation document in the docs folder of this repo that outlines how to use a third party react component?
I am relatively new to Fable and have only used React a little bit - are there areas that are more tricky, like HOCs or similar somewhat advanced features of React?
from fable-react.
This is funny, I was about to write that I hadn't used React HOCs so I didn't know, but just today I had to use them in my project and realized we're missing a helper in fable-react. I think we could add something like this:
open Fable.Core
open Fable.Import.React
open Fable.Helpers.React
open Fable.Helpers.React.Props
// Helper to be added to fable-react
let importHigherOrderComponent<[<Pojo>]'P> (importMember: string) (importPath: string) (fn: 'P->ReactElement): ComponentClass<'P> = jsNative
type [<Pojo>] MyProps =
{ index: int; value: string }
let SortableItem: ComponentClass<MyProps> =
importHigherOrderComponent "SortableElement" "react-sortable-hoc" (fun p ->
li [] [str p.value])
// To be used like...
let render () =
from SortableItem { index = 1; value = "foo" } []
But I'm not sure about a few things:
- Name?
importHigherOrderComponent
or something else? - Only for imported components or also accepting
ComponentClass
? - The generic
'Props
of the returned HOC should be always the same as the argument of the function argument? - Probably we also need to add a helper alias instead of
from
likeofType
,ofFunction
... MaybeofComponent
here?
@zaaack @MangelMaxime what do you think?
@danyx23 About the documentation, if you could send a PR that'd be great. Don't worry too much about the details, we can work on that later together. The important thing to keep in mind is Fable compiles directly to JS, not JSX. So usually calling React.createElement
, passing the component as the first element, a plain JS object containing the props, and filling the rest of arguments with children (as the fable-react helpers do) usually works.
from fable-react.
I never used HOC so I don't know and don't really understand the hight order think.
from fable-react.
@MangelMaxime They're used for example for react-sortable-hoc.
from fable-react.
from fable-react.
I know react-sortable-hoc, but never use it before. I'm OK with the naming, but not sure about the details, it's a rare case for me, but it looks really useful.
from fable-react.
I forgot to mention @vbfox to know his opinion about the helper for React HOCs (please see comment above).
from fable-react.
Did you make any progress on the importHigherOrderComponent? Was look for a way to integrate react-sortable-hoc into my project to day and found this thread but couldn't figure out whether you have implemented it y a different name
from fable-react.
Look at this comments: #84 (comment)
I think it should give you a solution
from fable-react.
@runefs We haven't added the helper yet to Fable.React but here's how I'm using react-sortable-hoc in my project, hope it helps:
Using react-sortable-hoc from Fable
open Fable.Helpers.React
open Fable.Core.JsInterop
/// Ugly helper that should be moved to fable-react
let inline hocOfImport<'P> (importMember: string) (importPath: string) (fn: 'P->ReactElement): ComponentClass<'P> =
!!((import importMember importPath) $ fn)
// let arrayMove(xs: 'a[], oldIndex: int, newIndex: int): 'a[] = importMember "react-sortable-hoc"
type SortableElementProps<'a> =
{
// SortableElement HOC props (cannot be used by wrapped component)
// https://github.com/clauderic/react-sortable-hoc#sortableelement-hoc
index: int
disabled: bool
// Custom props
rowIndex: int
key: string
value: 'a
handle: ComponentClass<unit>
renderItem: ComponentClass<unit> -> int -> 'a -> ReactElement
}
type SortEnd =
{ oldIndex: int
newIndex: int }
type SortableContainerProps<'a> =
{
// SortableContainer HOC props (cannot be used by wrapped component)
// https://github.com/clauderic/react-sortable-hoc#sortablecontainer-hoc
onSortEnd: SortEnd->unit
lockAxis: string
// Custom props
items: 'a list
handle: ComponentClass<unit>
useDragHandle: bool
renderItem: ComponentClass<unit> -> int -> 'a -> ReactElement
renderList: ReactElement list -> ReactElement
disabled: bool
}
let mkSortableHandle (f: unit -> ReactElement) =
hocOfImport "SortableHandle" "react-sortable-hoc" f
let mkSortableElement<'a> () =
hocOfImport "SortableElement" "react-sortable-hoc"
(fun (p: SortableElementProps<'a>) -> p.renderItem p.handle p.rowIndex p.value)
let mkSortableContainer<'a> (sortableElement: ComponentClass<SortableElementProps<'a>>) =
hocOfImport "SortableContainer" "react-sortable-hoc"
(fun (p: SortableContainerProps<'a>) ->
p.items |> List.mapi (fun i v ->
let a =
{
index = i
disabled = p.disabled
rowIndex = i
key = "item-" + string i // TODO: unique keys not depending on order
value = v
handle = p.handle
renderItem = p.renderItem
}
from sortableElement a [])
|> p.renderList)
type SortableComponentProps<'a> =
{
renderHandle: unit->ReactElement
renderItem: ComponentClass<unit> -> int -> 'a -> ReactElement
renderList: ReactElement list -> ReactElement
items: 'a list
/// oldIndex: int -> newIndex: int -> unit
handleSortChanged : int -> int -> unit
disabled: bool
}
type SortableComponent<'a>(p) =
inherit React.PureComponent<SortableComponentProps<'a>, unit>(p)
// Cache the SortableContainer HOC in the constructor so it's only necessary to build it once
let sortableContainer = mkSortableElement () |> mkSortableContainer
let sortableHandle = mkSortableHandle p.renderHandle
override this.render() =
from sortableContainer
{
// arrayMove(List.toArray this.props.items, i.oldIndex, i.newIndex)
onSortEnd = fun i -> this.props.handleSortChanged i.oldIndex i.newIndex
lockAxis = "y"
items = this.props.items
handle = sortableHandle
useDragHandle = true
renderItem = this.props.renderItem
renderList = this.props.renderList
disabled = this.props.disabled
} []
/// handleSortChanged: oldIndex: int -> newIndex: int -> unit
let mkSortable
(enabled: bool)
(renderList: ReactElement list -> ReactElement)
(renderItem: ComponentClass<unit> -> int -> 'a -> ReactElement)
(renderHandle: unit -> ReactElement)
(items: 'a list)
(handleSortChanged: int -> int -> unit) =
ofType<SortableComponent<'a>,_,_>
{
renderHandle = renderHandle
renderItem = renderItem
renderList = renderList
items = items
handleSortChanged = handleSortChanged
disabled = not enabled
} []
from fable-react.
Using a discriminated union props type as documented in using-third-party-react-components.md, how do you add support for IHTMLProp?
Fulma has a Props of IHTMLProp list
case in the options DU types but I'm not sure how to do that for 3rd party react components.
from fable-react.
Unfortunately this involves a bit of a trick at the moment. When passing the props to react we need to convert them to a JS object, which is done with keyValueList
. Right now, props nested in another union case are not supported by default, so you have to make the conversion by cheating the compiler as it's done for example here with the Style props:
fable-react/src/Fable.React.Props.fs
Lines 379 to 387 in 69ec32d
from fable-react.
Related Issues (20)
- React Server Components integration HOT 2
- Can't figure out how to wrap my view with a Higher Order Component HOT 4
- JsInterop helper for wrapping a higher order component HOT 2
- Can't reference React in Fable HOT 2
- Fable.ReactServer.cssProp very slow HOT 4
- Add Custom DU to DOMAttr HOT 1
- FunctionComponent.Lazy and SSR HOT 1
- Update samples to Fable 3
- ReactDOM.hydrate is no longer supported in React 18 HOT 17
- Can't update shared state passed with useContext? HOT 3
- Q: Use ReactElement import member for Storybook HOT 3
- Missing 'open' from Fable.React.Props? HOT 2
- Last Fable.React upgrade breaks my code HOT 7
- Publish source files from Fable.React.Types and Fable.ReactDom.Types to nuget HOT 5
- Fable.React version 8 depends on React.Dom gte 18 lt 19 according to femto
- Add Pointer Events HOT 3
- Why is useCallback not implemented? HOT 3
- How to obtain a component ref in a function component? HOT 5
- FunctionComponent.Of functions cache breaks reusable code HOT 1
- voidEl breaks with: $ELEMENT is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`. HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fable-react.