diff --git a/component.go b/component.go index f6f1065..f29e372 100644 --- a/component.go +++ b/component.go @@ -1,11 +1,43 @@ package react +import ( + "reflect" +) + type ComponentStruct interface { Render(ctx *Context) interface{} } func IsComponent(value interface{}) bool { - _, ok := value.(ComponentStruct) + ok := false + + if value != nil { + rVal := reflect.TypeOf(value) + _, ok = rVal.MethodByName("Render") + } return ok } + +func renderComponent(value interface{}, ctx interface{}) interface{} { + if !IsComponent(value) { + return nil + } + + rVal := reflect.ValueOf(value) + method := rVal.MethodByName("Render") + + if method.IsZero() || method.IsNil() { + return nil + } + + var result []reflect.Value + + if ctx != nil { + result = method.Call([]reflect.Value{reflect.ValueOf(ctx)}) + } else { + result = method.Call([]reflect.Value{reflect.ValueOf(NewContext())}) + } + + return result[0].Interface() +} diff --git a/component_test.go b/component_test.go index 917211d..2109808 100644 --- a/component_test.go +++ b/component_test.go @@ -22,6 +22,37 @@ func TestIsComponent(t *testing.T) { }) } +type LayoutMountPoints struct { + Head *Element + Header *Element + Content *Element +} + +type LayoutBaseComponent struct { + mounts *LayoutMountPoints +} + +func (l *LayoutBaseComponent) Render(ctx *Context) interface{} { + if l.mounts == nil { + l.mounts = &LayoutMountPoints{} + } + + return Document(&DocumentProps{ + Head: Fragment( + MetaCharset(), + l.mounts.Head, + ), + Body: Fragment( + CreateElement("header", nil, l.mounts.Header), + l.mounts.Content, + ), + }, nil) +} + +func LayoutBase(mounts *LayoutMountPoints) *LayoutBaseComponent { + return &LayoutBaseComponent{mounts: mounts} +} + func TestRenderClassLike(t *testing.T) { t.Run("it should correctly render component class like", func(t *testing.T) { content, err := Render(Div(nil, @@ -34,4 +65,32 @@ func TestRenderClassLike(t *testing.T) { assert.NoError(t, err) assert.Equal(t, "