From c5f444936bc72c60bf42ab466cb0e5b1f8f7f30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Cichoci=C5=84ski?= Date: Thu, 6 Sep 2018 21:45:56 +0200 Subject: [PATCH] Changes StackNavigator.Screen from stateless to statelessWithRetainedProps It allow us to check for header props changes and call navigation.setOptions when props changes. Should fix #122. Only problem are properties that are recreated every time like Style.t or (probably) Header.returnsComponent. --- example/Admin.re | 31 ++++++++++++++++++++----- src/StackNavigator.re | 52 +++++++++++++++++++++++++++++++++++++++--- src/StackNavigator.rei | 13 +++++++++-- 3 files changed, 85 insertions(+), 11 deletions(-) diff --git a/example/Admin.re b/example/Admin.re index 82c162a..f767c02 100644 --- a/example/Admin.re +++ b/example/Admin.re @@ -1,6 +1,11 @@ open Rebolt; -let component = ReasonReact.statelessComponent("Admin"); +type action = + | Increment; + +type state = {counter: int}; + +let component = ReasonReact.reducerComponent("Admin"); module Styles = { open Style; @@ -15,13 +20,15 @@ module Styles = { marginTop(Pt(16.)), backgroundColor(String(color)), borderRadius(20.), - width(Pt(100.)), + width(Pt(120.)), ]); let buttonText = style([textAlign(Center)]); let title = style([fontSize(Float(20.))]); }; -let renderButtons = (nav: NavigationConfig.StackNavigator.navigation) => +let getHeaderTitle = counter => "Admin" ++ string_of_int(counter); + +let renderButtons = (nav: NavigationConfig.StackNavigator.navigation, send) => style=(Styles.button("#ff9500")) onPress=(_e => nav.pop())> (ReasonReact.string("Pop")) + send(Increment))> + + (ReasonReact.string("Change header title")) + + ; let make = (~navigation, _children) => { ...component, - render: _self => + initialState: () => {counter: 0}, + reducer: (action, state) => + switch (action) { + | Increment => ReasonReact.Update({counter: state.counter + 1}) + }, + render: self => ...( @@ -47,7 +66,7 @@ let make = (~navigation, _children) => { (ReasonReact.string("Admin screen")) - (renderButtons(navigation)) + (renderButtons(navigation, self.send)) ) , diff --git a/src/StackNavigator.re b/src/StackNavigator.re index c19218e..676261a 100644 --- a/src/StackNavigator.re +++ b/src/StackNavigator.re @@ -541,8 +541,19 @@ module CreateStackNavigator = (Config: {type route;}) => { }, }; module Screen = { + type retainedProps = { + style: option(Style.t), + headerTitle: option(string), + /* headerStyle: option(Style.t), */ + headerLeft: option(Header.returnsComponent), + headerCenter: option(Header.returnsComponent), + headerRight: option(Header.returnsComponent), + animation: option(Animation.t), + }; + let flexOne = Style.(style([flex(1.)])); - let component = ReasonReact.statelessComponent("CallstackScreen"); + let component = + ReasonReact.statelessComponentWithRetainedProps("CallstackScreen"); let make = ( ~navigation: navigation, @@ -556,7 +567,16 @@ module CreateStackNavigator = (Config: {type route;}) => { children, ) => { ...component, - didMount: _self => { + retainedProps: { + style, + headerTitle, + /* headerStyle, */ + headerLeft, + headerCenter, + headerRight, + animation, + }, + didMount: _self => navigation.setOptions({ header: { title: headerTitle, @@ -567,7 +587,33 @@ module CreateStackNavigator = (Config: {type route;}) => { }, animation, style, - }); + }), + didUpdate: ({oldSelf: {retainedProps}}) => { + let propsChanged = + [ + retainedProps.style !== style, + retainedProps.headerTitle !== headerTitle, + /* oldSelf.retainedProps.headerStyle !== headerStyle, */ + retainedProps.headerLeft !== headerLeft, + retainedProps.headerCenter !== headerCenter, + retainedProps.headerRight !== headerRight, + retainedProps.animation !== animation, + ] + |> Belt.List.some(_, a => a); + + if (propsChanged) { + navigation.setOptions({ + header: { + title: headerTitle, + style: headerStyle, + center: headerCenter, + left: headerLeft, + right: headerRight, + }, + animation, + style, + }); + }; (); }, render: _self => { diff --git a/src/StackNavigator.rei b/src/StackNavigator.rei index 4afa6c3..282098f 100644 --- a/src/StackNavigator.rei +++ b/src/StackNavigator.rei @@ -40,6 +40,15 @@ module CreateStackNavigator: ); module Animation = Animation; module Screen: { + type retainedProps = { + style: option(Rebolt.Style.t), + headerTitle: option(string), + /* headerStyle: option(Rebolt.Style.t), */ + headerLeft: option(Header.returnsComponent), + headerCenter: option(Header.returnsComponent), + headerRight: option(Header.returnsComponent), + animation: option(Animation.t), + }; let make: ( ~navigation: navigation, @@ -55,8 +64,8 @@ module CreateStackNavigator: ReasonReact.componentSpec( ReasonReact.stateless, ReasonReact.stateless, - ReasonReact.noRetainedProps, - ReasonReact.noRetainedProps, + retainedProps, + retainedProps, ReasonReact.actionless, ); };