I am trying to implement a green, or red glow on a row depending if a number increases or decreases.
What is the best way to accomplish this?
Is there a way on mapStateToProps
or during render to compare the two?
I am trying to implement a green, or red glow on a row depending if a number increases or decreases.
What is the best way to accomplish this?
Is there a way on mapStateToProps
or during render to compare the two?
Since the component's render
-method only has access to the current props and state, you must keep information about how value changed in the current props and/or state. You must then indicate the change for (I assume) a brief amount of time.
There are several possibilities of where to do this listed below; pick one of them, not all. They all use the following utility fuction:
function getChange(value, prevValue) {
if (typeof prevValue === 'undefined') {
// If previos value did not exist, don't count it as a change.
// This is to avoid "feedback" the first time the value is rendered.
return;
}
if (value === prevValue) {
return;
}
return value < prevValue
? 'decrease'
: 'increase';
}
Read current state before disptatching an action. Note that this example requires you to use redux-thunk:
const changeValueTo = (value) => (dispatch, getState) => {
const prevValue = getState().value;
distpatch({
type: 'SET_VALUE',
change: getChange(value, prevValue),
value: value
});
}
function valueReducer(state = { value: void 0, change: void 0 }, action) {
switch (action.type) {
case 'SET_VALUE':
return {
value: action.value,
change: getChange(action.value, state.value)
};
default:
return state;
}
}
PS: void 0
is just a safe way to get undefined
.
PPS: We could just use state = {}
, but I prefer to be specific.
class Value extends React.Component {
state = {
change: 'black'
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
value: nextProps.value,
change: getChange(nextProps.value, prevState.value)
};
}
render() {
...
}
}
Like e.g. in componentDidUpdate
as suggested by Bruno Mazzardo.
Here I change the color of the text, but you can of course change the background or anything else.
/* css */
@keyframes red-fadeout {
from {
color: red;
}
to {
color: black;
}
}
@keyframes green-fadeout {
from {
color: green;
}
to {
color: black;
}
}
.decreased {
animation: 3s red-fadeout;
}
.increased {
animation: 3s green-fadeout;
}
// React
class Value extends React.Component {
...
render() {
const {
value,
change = '' // Assuming change is either 'increased', 'decreased' or falsy
} = this.props;
return (
<div className={change}>{value}</div>
);
}
}
You can use componentDidUpdate(prevProps, prevState), make the check inside it, accessing this.props and this.state, that will be updated, and based on that, setState({changed:this.props.number !== this.prevProps.number })
React documentation about lifecycle https://reactjs.org/docs/react-component.html#componentdidupdate for reference
You can use this.
this.setState((prevState, props) => {
if(props.step < 0)
{
return {counter: prevState.counter + props.step, color:'red'};
}
return {counter: prevState.counter + props.step, color:'blue'};
});
Based on this color in state component will render again. For more info visit. setState