This repository has been archived by the owner on Dec 13, 2023. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
140 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,95 @@ | ||
!!! warning | ||
Context is an unstable feature that's being *significantly* revised. See [issue #4](https://github.com/Roblox/roact/issues/4) for current progress. | ||
!!! danger "Unreleased API" | ||
This API is not yet available in a stable Roact release. | ||
|
||
!!! info | ||
This section is incomplete. It's possible that the context API will change before the existing API is ever documented. | ||
It may be available from a recent pre-release or Roact's master branch. | ||
|
||
[TOC] | ||
|
||
Roact supports a feature called context which enables passing values down the tree without having to pass them through props. Roact's Context API is based on [React's Context API](https://reactjs.org/docs/context.html). | ||
|
||
Context is commonly used to implement features like dependency injection, dynamic theming, and scoped state storage. | ||
|
||
## Basic Usage | ||
```lua | ||
local ThemeContext = Roact.createContext(defaultValue) | ||
``` | ||
|
||
Context objects contain two components, `Consumer` and `Provider`. | ||
|
||
The `Consumer` component accepts a `render` function as its only prop, which is used to render its children. It's passed one argument, which is the context value from the nearest matching `Provider` ancestor. | ||
|
||
If there is no `Provider` ancestor, then `defaultValue` will be passed instead. | ||
|
||
```lua | ||
local function ThemedButton(props) | ||
return Roact.createElement(ThemeContext.Consumer, { | ||
render = function(theme) | ||
return Roact.createElement("TextButton", { | ||
Size = UDim2.new(0, 100, 0, 100), | ||
Text = "Click Me!", | ||
TextColor3 = theme.foreground, | ||
BackgroundColor3 = theme.background, | ||
}) | ||
end | ||
}) | ||
end | ||
``` | ||
|
||
The `Provider` component accepts a `value` prop as well as children. Any of its descendants will have access to the value provided to it by using the `Consumer` component like above. | ||
|
||
Whenever the `Provider` receives a new `value` prop in an update, any attached `Consumer` components will re-render with the new value. This value could be externally controlled, or could be controlled by state in a component wrapping `Provider`: | ||
|
||
```lua | ||
local ThemeController = Roact.Component:extend("ThemeController") | ||
|
||
function ThemeController:init() | ||
self:setState({ | ||
theme = { | ||
foreground = Color3.new(1, 1, 1), | ||
background = Color3.new(0, 0, 0), | ||
} | ||
}) | ||
end | ||
|
||
function ThemeController:render() | ||
return Roact.createElement(ThemeContext.Provider, { | ||
value = self.state.theme, | ||
}, self.props[Roact.Children]) | ||
end | ||
``` | ||
|
||
## Legacy Context | ||
Roact also has a deprecated version of context that pre-dates the stable context API. It will be removed in a future release, but is currently maintained for backwards-compatibility. | ||
|
||
Legacy context values cannot be updated dynamically. It is up to the context user to create their own mechanism for updates, probably using a wrapper component and `setState`. | ||
|
||
To use it, add new entries to `self._context` in `Component:init()` to create a provider: | ||
|
||
```lua | ||
local Provider = Roact.Component:extend("FooProvider") | ||
|
||
-- Using a unique non-string key is recommended to avoid collisions. | ||
local FooKey = {} | ||
|
||
function Provider:init() | ||
self._context[FooKey] = { | ||
value = 5, | ||
} | ||
end | ||
``` | ||
|
||
...and read from that same value in `Component:init()` in your consumer component: | ||
|
||
```lua | ||
local Consumer = Roact.Component:extend("FooConsumer") | ||
|
||
function Consumer:init() | ||
self.foo = self._context[FooKey] | ||
end | ||
|
||
function Consumer:render() | ||
return Roact.createElement("TextLabel", { | ||
Text = "Foo: " .. self.foo.value, | ||
}) | ||
end | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,3 @@ | ||
.api-addition { | ||
display: flex; | ||
align-content: center; | ||
align-items: center; | ||
vertical-align: middle; | ||
|
||
padding: 0.4rem 0.6rem 0.4rem 0.5rem; | ||
background-color: #efffec; | ||
border-left: 0.2rem solid green; | ||
border-radius: 0.1rem; | ||
|
||
line-height: 1; | ||
font-size: 0.64rem; | ||
font-weight: bold; | ||
|
||
box-shadow: | ||
0 2px 2px 0 rgba(0,0,0,.14), | ||
0 1px 5px 0 rgba(0,0,0,.12), | ||
0 3px 1px -2px rgba(0,0,0,.2); | ||
} | ||
|
||
.api-addition::before { | ||
flex: 0 0 1.5rem; | ||
content: "+"; | ||
color: green; | ||
font-size: 1.5em; | ||
text-align: center; | ||
.md-typeset hr { | ||
border-bottom: 2px solid rgba(0, 0, 0, 0.15); | ||
} |