i create a use state in my react component like that:
const [loading, setLoading] = React.useState(false);
and in one project in return of component i saw something like this
<ListItemButton sx={{ color: `${loading && 'yellow'}` }}>
I can't find how that `${x && 'x' }` syntax works
Can someone explain to me or show me the documentation of this?
In this case `${loading && 'yellow'}` is the same as loading && 'yellow'
Strings surrounded in backticks ` are called template literals. It allows you tu put variables in strings.
`I'm ${name}. I'm ${age} years old.`
&& operators just means 'take the first falsey element and return it. If no falsey element is found, returns the last one.
0 && "" && "Banana" will return 0
"Banana" && "" && 0 will return ""
"Banana" && 1 && 2 will return 2
It's logical AND ( && ) operator, and next thing will execute incase if true condition
let yellow = true;
console.log( yellow && "Yellow color" )
let blue = false;
console.log( blue && "Blue color" )
Just simple plane javascript template literals
`${loading && 'yellow'}`
Will become
'yellow'
or
''
Depending on loading
Related
In my return statement, I try to check for a valid number or else assign the value 0. This doesn't seem to work, is there a different way of doing this?
return (
<Input
color="teal"
size="regular"
outline={true}
type={question?.type}
name={question?.name}
value={value ?? ''}
placeholder={question?.placeholder ?? ''}
onChange={(e: React.FormEvent<HTMLInputElement>) => {
if (question?.type === 'number' && Number(e.currentTarget.value) < 1) {
e.currentTarget.value = 0;
}
dispatch(
setResponseGeneric({
property: question?.name,
value: e.currentTarget.value,
})
);
}}
></Input>
);
This is because Number('bad input') returns NaN (Not a Number). NaN is a value which is not smaller or greater than 1. You should change your condition so that it handles those scenarios.
if (question?.type === 'number' && (isNaN(e.currentTarget.value) || Number(e.currentTarget.value) < 1)) {
Also something else, besides your question, changing the element value like you do in here e.currentTarget.value = 0; is bad practice since you're changing it imperatively. It's better to make sure you're changing the state so that the value variable becomes 0 (I'm not sure if that already happens in setResponseGeneric).
so I'm getting certain redmax and redmin values through props and I've stored them in a variable. The below code is inside render. This is how it looks:
if(props.gauge.id === 8){
let redMaxPressure = (props.gauge.params.red_max).split(',').map(function(i){
return parseInt(i,10)
})
let redMinPressure = (props.gauge.params.red_min).split(',').map(function(i){
return parseInt(i,10)
})
console.log('RedMax',redMaxPressure)
}
Now, I want to use those values inside the 'rect' svg but I'm unable to use that as it's throwing an error.
<rect
x={-0.305}
y={0.63}
rx={0.02}
width={0.6}
height={0.3}
fill={props.size !== 'small' && props.value <= redMaxPressure[0] ? rectColor : props.size === 'small' && props.value >=redMaxPressure[1] ? rectColor : '#ffffff00' }
stroke={'black'}
stroke-width={0.02}
/>
I'm getting an error for redMaxPressure[0] and redMaxPressure[1]. Is there a different way to use those values stored?
Note: The rect svg is inside return.
Your redMaxPressure, redMinPressure are not in scope of rect element, because currently they live (variables lifetime) only in if scope, so their values are undefined.
You should ensure they in scope:
let redMaxPressure = DEFAULT_MAX;
let redMinPressure = DEFAULT_MIN;
if(props.gauge.id === 8){
redMaxPressure = ...
redMinPressure = ...
}
return <rect fill={props.size !== 'small' && props.value <= redMaxPressure[0] ? rectColor : props.size === 'small' && props.value >=redMaxPressure[1] ? rectColor : '#ffffff00' } />
I need help to solve this
let someVar
render(
{
this.props.someData.map((items) =>
items.someotherData.map((item) =>
(item.data1 > 5 && item.data2 == "more") ? classNames({ "classname1": true })
: (item.data1 > 5 && item.data2 == "less") ? classNames({ "classname2": true })
: classNames({ "classname3": true })
))
}
<div className = { someVar } ></div>
)
I need my output of if loop to be pass to the variable
I tried many method. Nothing worked. Please give the solution
render() {
let someVar
this.props.someData.forEach(items =>
items.someotherData.forEach(item =>
item.data1 > 5 && item.data2 == 'more'
? someVar = 'classname1'
: item.data1 > 5 && item.data2 == 'less'
? someVar = 'classname2'
: someVar = 'classname3'
)
)
return <div className={someVar}></div>
}
I didn't really get what you were trying to do. Are you calling some function with the class names or something? Here is my best try to solve your problem though.
First we create the variable,
Then we do data processing. You shouldn't use map but instead the forEach if you are not returning anything. You are also overwriting the variable for each item (is this preferred behaviour?).
Then we actually return the React part of the code. Render function always needs to return JSX or null. Inside JSX we can use the someVar in the className. The final value of className needs to be a string. That's why we are putting strings to the someVar.
This is a JSX gist I'm displaying on the page.
rows.push(
<tr key={i}>
<td>{this.state['Person Name'] && this.state['Person Name'][i]}</td>
<td>{this.state['Amount'] && this.state['Amount'][i]}</td>
{this.state['Memo'] && this.state['Memo'].length > 0 ? <td>{this.state['Memo'][i]}</td> : undefined}
{this.state['Comment'] && this.state['Comment'].length > 0 ? <td>{this.state['Comment'][i]}</td> : undefined}
{this.state['Incurred Date'] && this.state['Incurred Date'].length > 0 ? <td>{this.state['Incurred Date'][i]}</td> : undefined}
{this.state['Entry Date'] && this.state['Entry Date'].length > 0 ? <td>{this.state['Entry Date'][i]}</td> : undefined}
<td>{this.state['Billable'] && this.state['Billable'][i]}</td>
<td>{this.state.fileName === 'expenses.csv' ? 'Expense' : 'Time'}</td>
</tr>
)
Somehow the conditions that are falsy still display empty <td>s to the table. What did I miss?
Empty columns are shown above.
You don't need to use ternary operators at all. Simply just chain &&'s.
{this.state.Memo && this.state.Memo[i] && <td>{this.state.Memo[i]}</td>}
{this.state.Comment && this.state.Comment[i] && <td>{this.state.Comment[i]}</td>}
{this.state['Incurred Date'] && this.state['Incurred Date'][i] && <td>{this.state['Incurred Date'][i]}</td>}
{this.state['Entry Date'] && this.state['Entry Date'][i] && <td>{this.state['Entry Date'][i]}</td>}
In addition, your array seems to be badly formatted:
// 2 separate variables for the same data?
this.memo = ['a', 'b'];
this.comment = ['comment', 'comment2'];
// Why not make it an array like this?
this.rows = [
{
Memo: 'a',
Comment: 'comment'
},
{
Memo: 'b',
Comment: 'comment2'
}
];
Then you can simply do:
this.rows.map(row => (
<tr key={row.id}>
<td>{row['Person Name']}</td>
<td>{row['Amount']}</td>
{this.state.hasMemos && <td>{row.Memo}</td>}
...
</tr>
)}
A <td> shouldn't be conditional on a row level, it should be conditional on a table level. You can't simply skip TD's if there isn't data for that row, as it will throw off the whole row by shifting columns over. You should either display N/A, an empty <td></td> for rows that may not have data, or hide them entirely on a table level via something like this.state.hasMemos, if there are any memos.
If you're using the new array structure I have listed, you can use this function to determine if any row has a memo:
this.array.some(row => row.Memo);
This will return true if any row has a Memo, thus either hiding the <td> for the entire table, or displaying it for every row.
When using angular, I had a very strange issue:
<div ng-app>
<textarea ng-model="resp" placeholder="Response"></textarea>
<a ng-show="resp">Respond</a>
</div>
Fiddle
When writing something into the textarea, the Respond link is shown.
However, strangely, when writing the letter 'f', the Respond button doesn't show.
A workaround for this is to use the condition resp.length>0, but I wonder why the letter 'f' behaves in a special way.
Actually 'f' is considered as false.
AngularJS uses the toBoolean function internally to evaluate ng-show / ng-hide expressions.
You should get the same behaviour for "f", "false", "0", "n", "no" and "[]".
You can read more about it here: https://github.com/angular/angular.js/issues/1229.
This is angular's toBoolean function:
function toBoolean(value) {
if (typeof value === 'function') {
value = true;
} else if (value && value.length !== 0) {
var v = lowercase("" + value);
value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
} else {
value = false;
}
return value;
}
Update:
In AngularJS 1.3+ this behaviour has been removed.
Quote: Due to bdfc9c02, values 'f', '0', 'false', 'no', 'n', '[]' are no longer treated as falsy. The only JavaScript values that are treated as falsy by the expression parser are now: false, null, undefined, NaN, 0 and "".
My recommendation would be to check to see if resp is an empty string. Since your textarea is a string value if the string is not empty then your respond text will be displayed.
<div ng-app>
<textarea ng-model="resp" placeholder="Response"></textarea>
<a ng-show="resp != ''">Respond</a>
</div>
Check out using strict checks for conditions. 'F', 'f', 'N', 'n', '0' also don't work in your fiddle. They are considered to be shortcuts for 'false'. Typing out 'false' also fails to show the 'Respond' button.
It's just the opposite, "f" is treated as false. Note that so are all the following:
"F"
"false"
"FALSE"
"FaLsE"
" faLse "
""
" "
" "
(i.e., case and leading/trailing whitespace do not matter)
However, partial words (e.g., "fa", "fal", "fals") are not.