Safe Haskell | None |
---|---|
Language | Haskell2010 |
React has lifecycle callbacks and refs that allows the class to interact with the browser DOM. React obtains a large performance boost from working with the virtual DOM instead of the browser DOM, so the use of these lifecycle callbacks should be minimized or not used at all (in fact, the example TODO app does not use them at all). Quoting the React documentation, "If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use refs to "make things happen" – instead, the data flow will usually accomplish your goal."
Additionally, the way GHCJS callbacks work causes potential problems with the lifecycle callbacks: GHCJS callbacks can block and if that occurs they either abort with an error or continue asyncronously. Continuing asyncronously cannot work because by their nature these lifecycle events are time-dependent, and by the time a Haskell thread resumes the element could have disappeared. Therefore, the lifecycle callbacks will abort with an error if one of them blocks. But because of the way GHCJS works, it is hard to control the possiblity of blocking since a lazily computed value that you just happen to demand might block on a blackhole. Therefore, this lifecycle view should only be used for simple things, such as scrolling to an element when it is mounted. This isn't a big restriction in my experience, since most of the time you just use views and the rare time you need a lifecycle event, it is to do something simple.
As an alternative to using this module and its resulting callback blocking complications, you can
consider writing the class in javascript/typescript/etc. and then using foreignClass
to call it
from Haskell.
- defineLifecycleView :: (Typeable props, Typeable state, NFData state) => String -> state -> LifecycleViewConfig props state -> ReactView props
- lifecycleConfig :: LifecycleViewConfig props state
- data LifecycleViewConfig props state = LifecycleViewConfig {
- lRender :: state -> props -> ReactElementM (StatefulViewEventHandler state) ()
- lComponentWillMount :: Maybe (LPropsAndState props state -> LSetStateFn state -> IO ())
- lComponentDidMount :: Maybe (LPropsAndState props state -> LDOM -> LSetStateFn state -> IO ())
- lComponentWillReceiveProps :: Maybe (LPropsAndState props state -> LDOM -> LSetStateFn state -> props -> IO ())
- lComponentWillUpdate :: Maybe (LPropsAndState props state -> LDOM -> props -> state -> IO ())
- lComponentDidUpdate :: Maybe (LPropsAndState props state -> LDOM -> LSetStateFn state -> props -> state -> IO ())
- lComponentWillUnmount :: Maybe (LPropsAndState props state -> LDOM -> IO ())
- data LPropsAndState props state = LPropsAndState {}
- data LDOM = LDOM {}
- type LSetStateFn state = state -> IO ()
Documentation
defineLifecycleView :: (Typeable props, Typeable state, NFData state) => String -> state -> LifecycleViewConfig props state -> ReactView props Source
Create a lifecycle view from the given configuration.
myView :: ReactView String myVew = defineLifecycleView "my view" (10 :: Int) lifecycleConfig { lRender = \state props -> ... , lComponentWillMount = \propsAndState setStateFn -> ... }
lifecycleConfig :: LifecycleViewConfig props state Source
A default configuration, which does not specify any lifecycle events. You should start with this and override the functions you need.
data LifecycleViewConfig props state Source
The class rendering function, together with optional callbacks for the various lifecycle events. As mentioned above, care must be taken in each callback to write only IO that will not block.
LifecycleViewConfig | |
|
data LPropsAndState props state Source
Actions to access the current properties and state.
type LSetStateFn state = state -> IO () Source
Set the state of the class.