问题
I'm trying to clarify some confusion (preferably from authoritative sources) about boolean props in React.
Suppose a have MyComponent
with several boolean props prop1
, prop2
...
First: it would seem that boolean props are like just others: you can define default values, either in defaultProps or in destructuring params:
const MyComponent = ({ prop1, prop2 }) => (
...
)
MyComponent.defaultProps = {
prop1: false,
prop2: true,
}
Or equivalently (no?)
const MyComponent = ({ prop1 = false, prop2 = true }) => (
...
)
What's not clear is how to pass values. The natural "React style", again, seems to be
<MyComponent prop1={ BOOLEAN_EXPRESION1 } prop2={ BOOLEAN_EXPRESION2 } />
... including the static literals (false/true
).
However, it's also stated that the correct (recommended?) way to pass boolean properties is presence/absence of the attribute, as HTML5 dictates.
So that, instead of <MyComponent prop1={true} prop2={false} />
, one should write <MyComponent prop1 />
.
My questions are:
What is the correct way of passing boolean props? Are both acceptable?
In case, HTML5 style is the recommended (or correct) way, how would one deal with dynamic values?
Furthermore, in case HTML5 style is acceptable, what about the default values? In the example above (where
prop2
istrue
by default), if I write<MyComponent />
, what would happen?
回答1:
Forenote:
Let's just think this differently and disregard rules established by HTML5 and focusing only on JSX. JSX has exactly two ways of passing true, <MyComponent prop />
and <MyComponent prop={true} />
and exactly one way of passing false <MyComponent prop={false} />
. I do agree this is an oddity distinguishing between HTML5 and JSX, but JSX is a syntax extension to JavaScript and not HTML so it does not need to conform to any of the rules of HTML.
From the JSX docs:
This funny tag syntax is neither a string nor HTML.
FYI, all rules and behavior of JSX is listed in React's JSX docs, and it includes how defaulting a prop to true works. Important note: these docs do not inherit anything from HTML and shouldn't be compared with HTML specs either.
Answers:
- What is the correct way of passing boolean props?
Passing an explicit true
in JSX:
There are exactly two ways to pass an explicit true
: passing true
and defaulting a prop to true:
<MyComponent prop={true} />
<MyComponent prop />
Note: As stated in the docs, JSX's behavior of defaulting a prop to true
is just an added feature that matches with HTML5's boolean attributes behavior.
Passing an explicit false
in JSX:
There is exactly one way to pass an explicit false
: passing false
<MyComponent prop={false} />
Note: This is where JSX's behavior differ from HTML5's boolean attributes behavior. There is not such thing as defaulting to false
in JSX; it is only applicable for passing an explicit true
. In contrast to HTML5, if you do not pass anything, you're really passing undefined
, and your defined default values will be used instead. This is contrary to the HTML5 specs which would say it's false
. Refer to the CodeSandbox link in the answer to #3 for this behavior.
Passing a boolean variable/expression in JSX:
Pass the variable or an expression to the prop:
// via variable
const foo = true;
<MyComponent prop={foo} />
const bar = false;
<MyComponent prop={bar} />
// via expression
<MyComponent prop={Math.random() > 0.5} />
Are both acceptable?
Referring to the way of passing an explicit true
vs defaulting a prop to true
, they are both acceptable in terms of compiling JSX. However, if you need consistency in a codebase for adhering to a certain style, add the ESLint rule jsx-boolean-value
. I personally use the Airbnb JavaScript style which turns that rule on. The guide emphasizes on readability, and so it decided for omitting the explicit true
.
- In case HTML5 style is the recommended (or correct) way , how would one deal with dynamic values?
Do not use HTML5 style (defaulting props to true
) for dynamic values (variables/expressions); use the React way of passing props (explicitly assigning prop values). See above for how to pass those.
- Furthermore, in case HTML5 style is acceptable, what about the default values? In the example above (where prop1,prop2 are resp. false/true by default) what would give?
Here are the final values for prop1
and prop2
passed respectively:
MyComponent.defaultProps = {
prop1: false,
prop2: true,
}
<MyComponent prop1 />
// prop1 == true
// prop2 == true // defaulted to true
<MyComponent prop1={true} prop2={false} />
<MyComponent prop1 prop2={false} />
// prop1 == true
// prop2 == false
Here is the CodeSandbox link: https://codesandbox.io/s/elated-davinci-izut1?fontsize=14&hidenavigation=1&theme=dark
Note: Not adding an attribute and then not passing a value (such as prop2
in the first example) is the same as passing undefined
unlike passing an explicit false
for the second example. Therefore, prop2
got defaulted to true
.
回答2:
Let me tell you about passing boolean values
HTML5 Style
<MyComponent
prop2 // equivalent prop2={true}, works only for static true values
prop1={false} // You can't do something like that for false though
/>
// example
<Select
multiSelect // You won't be changing this value throughout the whole life cycle
/>
// They will however transpiled to
React.createElement(MyComponent, {prop1: false, props2: true}, null)
// So passing true isn't necessarily a must
Default Props
This method isn't any different for boolean than other types
<MyComponent
title={title} // typeof title = string | undefined | null
bold={bold} // typeof bold = boolean | undefined | null
/>
// In case title being undefined or null,
// React will take the defaultProps
defaultProps
are equivalent to
static defaultProps = {
title: 'Hello World',
bold: true
}
props = {
title: props.title ?? 'Hello World',
bold: props.bold ?? true
}
// Or in function, it's much simpler and familiar
// Same as old C, if the props are undefined or null,
// default values will be taken, this is plain 'ol JS
const MyComponent = ({title = 'Hello World', bold = true}) => {
// boop
}
So to summarize and answer your question
- What is the correct way of passing boolean props? Are both acceptable?
Yes, both are acceptable. React is un-opinionated, It depends upon which style you're following, AirBnB recommends you to use HTML5 style for passing static true
values, while old TypeScript screams at you to change it to props2={true}
.
- In case, HTML5 style is the recommended (or correct) way, how would one deal with dynamic values?
HTML5 is applicable only for static true
values. There's simply no way for you to use dynamic boolean values in HTML5 style.
- Furthermore, in case HTML5 style is acceptable, what about the default values? In the example above (where prop2 is true by default), if I write
<MyComponent />
, what would happen?
<MyComponent />
will be transpiled to React.createElement(MyComponent, {}, null)
, meaning prop1
and prop2
will be undefined
. Given that the default values for prop1
is false
while prop2
is true
. Their respective default values will be taken.
回答3:
Depends on use case. Ever heard of separation of concerns? The same principle apply here. Handle it where it makes sense to handle. You can use variables in a component instead of defaultProps
(the React way). If its a switch pass it down from parent.
来源:https://stackoverflow.com/questions/60816731/how-are-boolean-props-used-in-react