This repository was archived by the owner on May 24, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 164
ISSUE-1463: Fixed undefined prop type error #1696
Merged
Merged
Changes from 1 commit
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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 |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| /* eslint-disable import/no-extraneous-dependencies */ | ||
|
||
| import React from 'react'; | ||
| import PropTypes from 'prop-types'; | ||
| import { parse } from 'react-docgen'; | ||
| import Markdown from 'terra-markdown'; | ||
| import classNames from 'classnames/bind'; | ||
| import styles from './PropsTable.scss'; | ||
|
|
||
| const cx = classNames.bind(styles); | ||
|
|
||
| const propTypes = { | ||
| /** | ||
| * Title of component | ||
| */ | ||
| componentName: PropTypes.string, | ||
| /** | ||
| * Markdown source file | ||
| */ | ||
| src: PropTypes.string.isRequired, | ||
| }; | ||
|
|
||
| function formatShape(shape) { | ||
| return JSON.stringify(shape, null, 1); | ||
| } | ||
|
|
||
| function determineType(type) { | ||
| let typeName = type.name; | ||
|
|
||
| if (typeName === 'enum') { | ||
| <<<<<<< HEAD | ||
| if (Number.isNaN(Number(type.value[0].value))) { | ||
| typeName = typeof type.value[0].value; | ||
| } else { | ||
| typeName = 'number'; | ||
| } | ||
| ======= | ||
| typeName = 'enum'; | ||
| >>>>>>> c55554b1... ISSUE-1463: Fixed undefined prop type error | ||
| } else if (typeName === 'arrayOf') { | ||
| if (type.value.name === 'shape') { | ||
| typeName = <span> array of objects structured like: <pre className={cx('props-table-pre')}> {formatShape(type.value.value)} </pre></span>; | ||
| } else { | ||
| typeName = `array of ${type.value.name}s`; | ||
| } | ||
| } else if (typeName === 'union') { | ||
| const options = type.value.map((option) => { | ||
| const name = option.name === 'shape' ? (( | ||
| <span key={option.value}> an object structured like: | ||
| <pre className={cx('props-table-pre')}> {formatShape(option.value)} </pre> | ||
| </span> | ||
| )) : (<span key={option.name}> {option.name}</span>); | ||
| return name; | ||
| }); | ||
| typeName = options.reduce((curr, next) => [curr, <span key={`${curr.value}-${next.value}`}> or </span>, next]); | ||
| } else if (typeName === 'shape') { | ||
| typeName = <span> an object structured like: <pre className={cx('props-table-pre')}> {formatShape(type.value)} </pre></span>; | ||
| } | ||
|
|
||
| return typeName; | ||
| } | ||
|
|
||
| /** | ||
| * Renders a table view for the props metadata of a react component generated by react-docgen | ||
| */ | ||
| const PropsTable = ({ componentName, src, ...customProps }) => { | ||
| /** | ||
| * Runs component source code through react-docgen | ||
| * @type {Object} | ||
| */ | ||
| const componentMetaData = parse(src); | ||
|
|
||
| /** | ||
| * Alias for props object from componentMetaData | ||
| * @type {Object} | ||
| */ | ||
| const componentProps = componentMetaData.props; | ||
|
|
||
| const tableRowClass = cx('prop-table-row'); | ||
| const tableClassNames = cx([ | ||
| 'props-table', | ||
| customProps.className, | ||
| ]); | ||
|
|
||
| return ( | ||
| <div dir="ltr" className="markdown-body"> | ||
| <h2>{componentName} Props</h2> | ||
| <table {...customProps} className={tableClassNames}> | ||
| <thead> | ||
| <tr> | ||
| <th className={cx('prop-table-name')}>Prop Name</th> | ||
| <th className={cx('prop-table-type')}>Type</th> | ||
| <th className={cx('prop-table-required')}>Is Required</th> | ||
| <th className={cx('prop-table-default')}>Default Value</th> | ||
| <th className={cx('prop-table-description')}>Description</th> | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| {Object.keys(componentProps).map((key) => { | ||
| const prop = componentProps[key]; | ||
| const type = determineType(prop.type); | ||
|
|
||
| return ( | ||
| <tr className={tableRowClass} key={key} style={{ fontSize: '90%' }}> | ||
| <td style={{ fontWeight: 'bold' }}>{key}</td> | ||
| <td>{(prop.type ? type : '')}</td> | ||
| {(prop.required ? | ||
| <td style={{ color: '#d53700' }}>required</td> | ||
| : <td style={{ color: '#444' }}>optional</td>)} | ||
| {(prop.defaultValue ? | ||
| <td style={{ fontWeight: 'bold' }}>{prop.defaultValue.value}</td> | ||
| : <td style={{ color: '#444' }}>none</td>)} | ||
| <td><Markdown src={prop.description} /></td> | ||
| </tr> | ||
| ); | ||
| })} | ||
| </tbody> | ||
| </table> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| PropsTable.propTypes = propTypes; | ||
|
|
||
| export default PropsTable; | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Ohh I think I miss understood what you meant when you had asked me about this change.
enumwould not be the correct prop type in most cases, I thought you meant you would parse the first value to determine the type. Looking in the terra-repos,oneOfis usually anenum of stringsoptions... so this maps to a string prop essentially.If we only indicate an
enum, this would still require one to look in the code to verify the enum options.Additionally, to me this indicated a more 'rigid' prop value than what will be required by most props.
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.
What was the reason this was displayed as undefined? I know this occurs because we want to pass
Object.keys(DEFAULTS), but what information is given as the type value?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.
Listing the available enum keys in the code comment above the prop that generates the doc could help with this
In previous meetings we've talked about not using enums as propTypes but still exporting them so people could use them if they wanted. For example, in the card props image, we'd make the propType a string and list out the values we accept while also exporting an enum that's values were strings. Users could type the string directly or use the enum.
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.
I've dug into the react-docgen code a bit more and it looks like they may handle the case #1463 was logged for.
We've opted to do custom type checking, so we miss out on this feature from react-docgen, but I'd recommend taking a look at this PR and this PR which seem to have added support in react-docgen for resolving
Object.keys()inPropType.oneOf()and potentially resolving spreads. Here is a util they've made to help resolve enums.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.
This was displaying as undefined because when we would try to examine
typeof type.value[0].value, we would in fact be trying to calltypeofonObject.values(<whatever the name of your enumerated object was>), rather than on[/*the actual array that Object.values() returns */]– essentially, we'd be making the call before theObject.valueswas evaluated, and hence before the objects values were converted into an array. So trying to access the first item intype.valueand look at it'svaluewould returnundefined, sotypeNamewas inadvertently getting set toundefinedhere.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.
@dylan-sftwr @bjankord Ah I see what you are saying the issue is. ok. LGTM.