-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
React fiber support #1443
React fiber support #1443
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1443 +/- ##
==========================================
+ Coverage 14.34% 14.54% +0.19%
==========================================
Files 201 202 +1
Lines 4614 4649 +35
Branches 503 570 +67
==========================================
+ Hits 662 676 +14
+ Misses 3527 3474 -53
- Partials 425 499 +74
Continue to review full report at Codecov.
|
We should look for a react-provided |
@xavcz thanks so much for getting this going! We obviously need to support new versions of React in storybook/storyshots. As far as stories themselves, might it make sense to restrict them to valid elements? String/number stories don't seem super useful, and array stories also seem dubious... So even though react supports them, does it mean we need to allow people to write stories with those? |
Yes, I believe so |
Can we use this: https://facebook.github.io/react/docs/react-api.html#isvalidelement |
Found some info there on the |
@xavcz @ndelangen I still don't understand why it's necessary to support non-elements for the story renderer function just because it's possible in React fiber. If I write a component that's a react element that uses some of these new features, that will work without modifying storybook, correct? |
@xavcz do you think they'll update |
@shilman actually no! 😞 the preview's render checks on
@tmeasday no idea! 😅 having an This would be something like: // return true if the element is renderable with react fiber
const checkFiberRenderableTypes = element =>
typeof element === 'string' ||
typeof element === 'number' ||
React.isValidElement(element);
// return true if renderable
// else return false
const isReactRenderable = element => {
// storybook is running with a version prior to fiber,
// run a simple check on the element
if (/* react version is below fiber */) {
return React.isValidElement(element);
}
// the element is not an array, check if its a fiber renderable element
if (!Array.isArray(element)) {
return checkFiberRenderableTypes(element);
}
// the element is an array, loop on its elements to see if its ok to render them
return element
// run this function on every item
.map(isReactRenderable)
// try to find a false value in this possibly deep nested array
// -> if there is a false value, that means it cannot render
}; |
🔂 the element check before rendering the preview is back: // before
if (element.type === undefined) {
renderError(/* ... */)
}
// now
if (isReactRenderable(element)) {
renderError(/* ... */)
} This
I've added some tests for the utilities I created and the I've add a lot of fun doing this and learnt a lot! 😊 Based on the previous discussion, if you believe this check / PR is superfluous: feel free to close it, no bother 👌 |
|
||
// input: [1, 2, [3, 4, [5, 6, [7]]]] | ||
// output: [ 1, 2, 3, 4, 5, 6, 7 ] | ||
export const flattenList = list => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import { flattenDeep } from 'lodash'
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌 definitely! I was hesitant to import lodash
as I saw very few use of it in the project! 👍 will replace this function by lodash.flattenDeep
!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated! ✅
const elementsList = element.map(isReactRenderable); | ||
|
||
// flatten the list of elements (possibly deep nested) | ||
const flatList = flattenList(elementsList); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is it possibly deep nested if you are running element.map
in the previous line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hehe, I personally wouldn't design a component deep nested, but it could be possible:
const WeirdComponent = () => [
<div>Some list</div>,
[
<Something />,
<div>This component is technically valid</div>,
<em>But weird</em>
],
<strong>Y U LIST</strong>,
];
Note: in this case, we should maybe throw an error: "Break this component in smaller ones for your sanity sake!" 😂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But if element is an array, then array.map(fn) is going to return an array, not a deeply-nested array?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh sorry, it's recursive. nevermind 😄
@xavcz minor comments on your latest commit, otherwise I think it looks great! |
Thanks @xavcz !!! Will merge as soon as the build finishes 👍 🎉 ❤️ |
😮 Problem
Let's assume you use
react@16.x.y(-alpha-z)
and you write a story as similar as this one:In the React preview
There is a specific check on the
element
to render in the preview which prevents using the new "rendering features" of React Fiber: array, string, number.If you write a story as similar as the one shown above, the UI will throw errors as seen in this screencast.
In Storyshots (-> Jest -> Node)
requestAnimationFrame
is used in React Fiber, and doesn't exist in Node env, and so Jest (storyshots
). It appears that it's something that needs to be fixed at the whole app level, it's not only a Storyshots issue. See screenshot.✍️ What I did
on the UI
Simply remove the check, and let
ReactDOM
throws an error if the element is invalid.Here is a screencast of what's happening without this check:
Without the
element.type === undefined
check:for Storyshots (/ Jest)
If somebody decides to use React Fiber and Jest, they needs to manually mock
requestAnimationFrame
(at the moment! 🤙).We can do like explained in this comment: facebook/react#9102 (comment).
📟 How to test
Setup using the
examples/test-cra
appAdd the following story to
stories/index.js
:Preview test
Then, go to http://localhost:9009.
Storyshots test
Create a
__mocks_
folder in the root folder and add areact.js
file in it:Add the following in
react.js
:yarn test
❓ Questions
Should we keep the preview check and replace it by a function like
isValidElement
checking whether it's an element, a number, a string, or an array (and at elements inside it)?What do you think? 🤔