Skip to content

Commit 4ea3a9e

Browse files
authored
Merge pull request #13 from mvsmal/react-fragment
React fragment support
2 parents ae8e173 + 6394547 commit 4ea3a9e

4 files changed

Lines changed: 33 additions & 1 deletion

File tree

src/Interop.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ module Interop =
2626

2727
let inline createElement name (props: IReactProperty list) : ReactElement =
2828
Element (name, props)
29+
let inline createElements (elements : ReactElement seq) : ReactElement =
30+
Elements elements
2931
let inline createVoidElement name (props: IReactProperty list) : ReactElement =
3032
VoidElement (name, props)
3133
let inline createTextElement (content : string) = ViewBuilder.escape content |> TextElement

src/React.fs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,10 @@ type React =
4242
/// <param name='withKey'>A function to derive a component key from the props.</param>
4343
static member functionComponent(name: string, render: 'props -> #seq<ReactElement>, ?withKey: 'props -> string) =
4444
render
45+
46+
/// <summary>
47+
/// The `React.fragment` component lets you return multiple elements in your `render()` method without creating an additional DOM element.
48+
/// </summary>
49+
/// <param name='elements'>A collection of elements to render without parent</param>
50+
static member fragment(elements : #seq<ReactElement>) =
51+
Interop.createElements elements

src/ViewEngine.fs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ and ReactElement =
2929
| Element of string * IReactProperty list // An element which may contain properties
3030
| VoidElement of string * IReactProperty list // An empty self-closed element which may contain properties
3131
| TextElement of string
32+
| Elements of ReactElement seq
3233

3334
[<RequireQualifiedAccess>]
3435
module ViewBuilder =
@@ -87,6 +88,9 @@ module ViewBuilder =
8788
match children, text, attrs with
8889
| _, Some text, _ -> buildParentNode (name, attrs, TextElement text :: children)
8990
| _ -> buildParentNode (name, attrs, children)
91+
| Elements elements ->
92+
for element in elements do
93+
buildNode isHtml sb element
9094

9195
let buildXmlNode = buildNode false
9296
let buildHtmlNode = buildNode true

test/ViewEngineTest.fs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,23 @@ let ``Nested content should render correctly`` () =
218218
let html =
219219
nested
220220
|> Render.xmlView
221-
Assert.Equal("<div><!-- this is a test --><h1>Header</h1><p><br/><strong>Ipsum</strong> dollar</p></div>", html)
221+
Assert.Equal("<div><!-- this is a test --><h1>Header</h1><p><br/><strong>Ipsum</strong> dollar</p></div>", html)
222+
223+
[<Fact>]
224+
let ``Fragment works correctly`` () =
225+
let withFragment =
226+
Html.div [
227+
prop.className "test-class"
228+
prop.children [
229+
Html.p "test outer p"
230+
React.fragment [
231+
Html.p "test inner p"
232+
Html.span "test span"
233+
]
234+
]
235+
]
236+
237+
let html =
238+
withFragment
239+
|> Render.htmlView
240+
Assert.Equal("<div class=\"test-class\"><p>test outer p</p><p>test inner p</p><span>test span</span></div>", html)

0 commit comments

Comments
 (0)