Dynamic attribute in ReactJS
ReactjsReactjs Problem Overview
I want to dynamically include/omit the disabled attribute on a button element. I have seen plenty of examples of dynamic attribute values, but not of attributes themselves. I have the following render function:
render: function() {
var maybeDisabled = AppStore.cartIsEmpty() ? "disabled" : "";
return <button {maybeDisabled}>Clear cart</button>
}
This throws a parse error because of the "{" character. How can I include/omit the disabled attribute based on the (boolean) result of AppStore.cartIsEmpty()?
Reactjs Solutions
Solution 1 - Reactjs
The cleanest way to add optional attributes (including disabled
and others you might want to use) is currently to use JSX spread attributes:
var Hello = React.createClass({
render: function() {
var opts = {};
if (this.props.disabled) {
opts['disabled'] = 'disabled';
}
return <button {...opts}>Hello {this.props.name}</button>;
}
});
React.render((<div><Hello name="Disabled" disabled='true' />
<Hello name="Enabled" />
</div>)
, document.getElementById('container'));
By using spread attributes, you can dynamically add (or override) whatever attributes you'd like by using a javascript object instance. In my example above, the code creates a disabled
key (with a disabled
value in this case) when the disabled
property is passed to the Hello
component instance.
If you only want to use disabled
though, this answer works well.
Solution 2 - Reactjs
You can pass a boolean to the disabled
attribute.
render: function() {
return <button disabled={AppStore.cartIsEmpty()}>Clear cart</button>
}
function Test() {
return (
<div>
<button disabled={false}>Clear cart</button>
<button disabled={true}>Clear cart</button>
</div>
);
}
ReactDOM.render(<Test />, document.querySelector("#test-container"));
console.log(Array.from(document.querySelectorAll("button")));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="test-container"></div>
Solution 3 - Reactjs
I'm using React 16 and this works for me (where bool
is your test):
<fieldset {...(bool && {disabled:true})}>
Basically, based on the test (bool
) you return an object with the conditional attributes or you don't.
Also, if you need to add or omit multiple attributes you can do this:
<fieldset {...(bool && {disabled:true, something:'123'})}>
For more elaborate attribute managed I suggest you prefab the object with (or without) the attributes outside of JSX.
Solution 4 - Reactjs
Far cleaner than the accepted solution is the solution which AnilRedshift mentioned, but which I'll expand on.
Simply put, HTML attributes have a name and a value. As a shorthand, you can use the name only for "disabled", "multiple", etc. But the longhand version still works, and allows for React to work in it's preferred way.
disabled={disabled ? 'disabled' : undefined}
is the most legible solution.
Solution 5 - Reactjs
The version I used was:
<button disabled={disabled ? 'disabled' : undefined}>
Click me (or dont)
</button>
Solution 6 - Reactjs
More cleaner way of doing dynamic attributes which works for any attributes is
function dynamicAttributes(attribute, value){
var opts = {};
if(typeof value !== 'undefined' && value !== null) {
opts['"'+attribute+'"'] = value;
return opts;
}
return false;
};
Call in your react component like following
<ReactComponent {...dynamicAttributes("disabled",false)}
{...dynamicAttributes("data-url",dataURL)}
{...dynamicAttributes("data-modal",true)} />
Tips :
-
You could have
dynamicAttributes
function in a common place/utilities and import it to use it across all components -
you could pass value as
null
to not render dynamic attribute
Solution 7 - Reactjs
A simple and clean way of doing it
<button {...disabled && {disabled: true}}>Clear cart</button>
disabled should come from props like this
<MyComponent disabled />
Solution 8 - Reactjs
You can find something similar to this at the documentation.
https://facebook.github.io/react/docs/transferring-props.html
In your case could be something like this
function MyComponent(props) {
let { disabled, ...attrs } = props;
if (disabled) {
// thus, it will has the disabled attribute only if it
// is disabled
attrs = {
...attrs,
disabled: true
}
};
return (
<button {...attrs}>MyLabel</button>
)
}
This code is using ES6, but I thing you got the idea.
This is cool because you can pass many others attributes to this component and it will still work.
Solution 9 - Reactjs
First you can simply check
<button disabled={true}>Button 1</button>
<button disabled={false}>Button 2</button>
Note: **disabled value is not String, it should be Boolean.
Now for dynamic. You can simply write
<button type="button" disabled={disable}
onClick={()=>this.setSelectValue('sms')} >{this.state.sms}</button>
As you can see I am using disabled property and in curly brackets it can be local variable/state var.
The variable disable
contains values true/false.
Solution 10 - Reactjs
This could work, problem with disabled is one could not simply set boolean for it.
if(AppStore.cartIsEmpty()){
return "<button disabled>Clear cart</button>"
}
else
{
return "<button>Clear cart</button>"
}