Skip to content

Add React.memo #112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 6, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions src/Fable.React/Fable.Helpers.React.fs
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,12 @@ let inline fn<'P> (f: 'P -> ReactElement) (props: 'P) (children: ReactElement se
let inline ofImport<'P> (importMember: string) (importPath: string) (props: 'P) (children: ReactElement seq): ReactElement =
createElement(import importMember importPath, props, children)

type ReactElementType<'props> = interface end

type ReactComponentType<'props> =
inherit ReactElementType<'props>
abstract displayName: string option with get, set

#if FABLE_COMPILER
/// Alias of `ofString`
let inline str (s: string): ReactElement = unbox s
Expand Down Expand Up @@ -878,6 +884,61 @@ let inline ofList (els: ReactElement list): ReactElement = unbox(List.toArray el
/// Returns an array **from .render() method**
let inline ofArray (els: ReactElement array): ReactElement = unbox els

[<RequireQualifiedAccess>]
module ReactElementType =
let inline ofComponent<'comp, 'props, 'state when 'comp :> Component<'props, 'state>> : ReactComponentType<'props> =
unbox jsConstructor<'comp>

let inline ofFunction<'props> (f: 'props -> ReactElement) : ReactComponentType<'props> =
unbox f

let inline ofHtmlElement<'props> (name: string): ReactElementType<'props> =
unbox name

/// Create a ReactElement to be rendered from an element type, props and children
let inline create<'props> (comp: ReactElementType<'props>) (props: 'props) (children: ReactElement seq): ReactElement =
createElement(comp, props, children)

type PropsEqualityComparison<'props> = 'props -> 'props -> bool

[<Import("memo", from="react")>]
let private reactMemo<'props> (render: 'props -> ReactElement) : ReactComponentType<'props> =
jsNative

/// React.memo is a higher order component. It’s similar to React.PureComponent but for function components instead of
/// classes.
///
/// If your function component renders the same result given the same props, you can wrap it in a call to React.memo
/// for a performance boost in some cases by memoizing the result. This means that React will skip rendering the
/// component, and reuse the last rendered result.
///
/// By default it will only shallowly compare complex objects in the props object. If you want control over the
/// comparison, you can use `memoWith`.
let memo<'props> (name: string) (render: 'props -> ReactElement) : ReactComponentType<'props> =
render?displayName <- name
reactMemo(render)

[<Import("memo", from="react")>]
let private reactMemoWith<'props> (render: 'props -> ReactElement, areEqual: PropsEqualityComparison<'props>) : ReactComponentType<'props> =
jsNative

/// React.memo is a higher order component. It’s similar to React.PureComponent but for function components instead of
/// classes.
///
/// If your function component renders the same result given the same props, you can wrap it in a call to React.memo
/// for a performance boost in some cases by memoizing the result. This means that React will skip rendering the
/// component, and reuse the last rendered result.
///
/// This version allow you to control the comparison used instead of the default shallow one by provide a custom
/// comparison function.
let memoWith<'props> (name: string) (areEqual: PropsEqualityComparison<'props>) (render: 'props -> ReactElement) : ReactComponentType<'props> =
render?displayName <- name
reactMemoWith(render, areEqual)

/// Create a ReactElement to be rendered from an element type, props and children
let inline ofElementType<'props> (comp: ReactElementType<'props>) (props: 'props) (children: ReactElement seq): ReactElement =
ReactElementType.create comp props children

#else
/// Alias of `ofString`
let inline str (s: string): ReactElement = HTMLNode.Text s :> ReactElement
Expand Down