Skip to content
This repository has been archived by the owner on Dec 13, 2023. It is now read-only.

Add stackTrace getter #93

Merged
merged 6 commits into from
May 16, 2018
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Added the static lifecycle method `getDerivedStateFromProps` ([#57](https://github.com/Roblox/roact/pull/57))
* Allow canceling render by returning nil from setState callback ([#64](https://github.com/Roblox/roact/pull/64))
* Added `defaultProps` value on stateful components to define values for props that aren't specified ([#79](https://github.com/Roblox/roact/pull/79))
* Added `getElementTraceback` ([#81](https://github.com/Roblox/roact/issues/81), [#93](https://github.com/Roblox/roact/pull/93))

## 1.0.0 Prerelease 2 (March 22, 2018)
* Removed `is*Element` methods, this is unlikely to affect anyone ([#50](https://github.com/Roblox/roact/pull/50))
Expand Down
7 changes: 7 additions & 0 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,13 @@ Right now, components are re-rendered any time a parent component updates, or wh

`PureComponent` implements `shouldUpdate` to only trigger a re-render any time the props are different based on shallow equality. In a future Roact update, *all* components may implement this check by default.

### getElementTraceback
```
getElementTraceback() -> string | nil
```

`getElementTraceback` gets the stack trace that the component was created in. This allows you to report error messages accurately.

## Lifecycle Methods
In addition to the base Component API, Roact exposes additional lifecycle methods that stateful components can hook into to be notified of various steps in the rendering process.

Expand Down
8 changes: 8 additions & 0 deletions lib/Component.lua
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,14 @@ function Component:setState(partialState)
self:_update(self.props, newState)
end

--[[
Returns the current stack trace for this component, or nil if the
elementTracing configuration flag is set to false.
]]
function Component:getElementTraceback()
return self._handle._element.source
end

--[[
Notifies the component that new props and state are available. This function
is invoked by the reconciler.
Expand Down
48 changes: 48 additions & 0 deletions lib/Component.spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ return function()
local Core = require(script.Parent.Core)
local Reconciler = require(script.Parent.Reconciler)
local Component = require(script.Parent.Component)
local GlobalConfig = require(script.Parent.GlobalConfig)

it("should be extendable", function()
local MyComponent = Component:extend("The Senate")
Expand Down Expand Up @@ -523,4 +524,51 @@ return function()
Reconciler.unmount(instance)
end)
end)

describe("getElementTraceback", function()
it("should return stack traces", function()
local stackTraceCallback = nil

GlobalConfig.set({
elementTracing = true
})

local TestComponent = Component:extend("TestComponent")

function TestComponent:init()
stackTraceCallback = function()
return self:getElementTraceback()
end
end

function TestComponent:render()
return Core.createElement("StringValue")
end

local handle = Reconciler.mount(Core.createElement(TestComponent))
expect(stackTraceCallback()).to.be.ok()
Reconciler.unmount(handle)
GlobalConfig.reset()
end)

it("should return nil when elementTracing is off", function()
local stackTraceCallback = nil

local TestComponent = Component:extend("TestComponent")

function TestComponent:init()
stackTraceCallback = function()
return self:getElementTraceback()
end
end

function TestComponent:render()
return Core.createElement("StringValue")
end

local handle = Reconciler.mount(Core.createElement(TestComponent))
expect(stackTraceCallback()).to.never.be.ok()
Reconciler.unmount(handle)
end)
end)
end