Relatively new to react. I've not seen this done often. Example:
this.state = {
varName: x.length != 0 ? 'Something' : null
}
Usually, you will define the initial state in the constructor with initial values, then on a component lifecycle, you could setState to that condition. Example
constructor(props) {
super(props);
this.state = {
varName:null
};
}
componentDidMount() {
// perhaps here evaluate your x value and then set the state
var x = something such as fetch or props passed
this.setState({
varName: x.length != 0 ? 'Something' : null
})
}
I don't see why that wouldn't work, but you'd have to be careful about where x is being defined. Usually I just leave all my state variables set to null or default values and then update them in componentWillMount, when I'll grab the information needed from props, localstorage, etc
Related
How can you change the status as an object? I did it this way, but I don't think it's right, because in compiling it gives a setState warn.
I would like to understand how to change a state whose value is an object.
class Animation extends React.Component {
constructor(props) {
super(props);
this.state = {
step : step,
ledge :{zoom:1, display:"flex"},
map :{zoom:0, x:0, y:0, rotate:0},
};
}
StepForward = () => {
step = step + 1;
//STEP 1
if(step === 1){
this.setState({
...this.state.ledge.zoom = this.state.ledge.zoom - 1,
...this.state.ledge.display = "none"
});
}
}
StepBack = () => {
step = step - 1;
if(step < 0 ){
this.setState({step:step})
step = -1
}
//STEP 0
if(step === 0){
this.setState({
...this.state.ledge.zoom = this.state.ledge.zoom + 1,
...this.state.ledge.display = "flex",});
}
}
render() {
return (
<div id="content_animation">
<div id="step back" class="command" onClick={this.StepBack}>
<img class="arrow" src="img/arrow_b.svg" alt="back"/>
</div>
<div id="animation">
<AnimationStep
step = {this.state.step}
ledge={this.state.ledge}
map={this.state.map}/>
</div>
<div id="step forward" class="command" onClick={this.StepForward}>
<img class="arrow" src="img/arrow_f.svg" alt="forward"/>
</div>
</div>
)
}
}
export default Animation
when I compile it gives me the error that you see below but if you insert a comment above the line of code "wrong", then it works and compiles correctly ...
Compiled with warnings.
Do not mutate state directly. Use setState() react/no-direct-mutation-state
Do not mutate state directly. Use setState() react/no-direct-mutation-state
Do not mutate state directly. Use setState() react/no-direct-mutation-state
Do not mutate state directly. Use setState() react/no-direct-mutation-state
Search for the keywords to learn more about each warning.
To ignore, add //eslint-disable-next-line to the line before.
As the error clearly states, you're mutating your state directly, which will cause bugs along the way. You can set state without mutating it like this:
this.setState(state => ({
...state,
ledge: {
...state.ledge,
zoom: state.ledge.zoom - 1,
display: 'none'
}
}));
Useful links:
Mutating state - https://daveceddia.com/why-not-modify-react-state-directly/
Functional setState - https://www.freecodecamp.org/news/functional-setstate-is-the-future-of-react-374f30401b6b/
Object spreading - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals
The problem is with your setState calls and how you're setting those values:
this.setState({
ledge: {
zoom: this.state.ledge.zoom - 1,
display: 'none'
}
});
Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.
You perhaps would love to check difference between mutable and immutable aswell.
What you should do in this case you could use spread operator :
this.setState(prevState => ({
ledge: { // object that we want to update
...prevState.ledge, // keep all other key-value pairs
zoom: this.state.ledge.zoom -1 // update the value of specific key
}
}))
When you use this.setState, you don't have to explicitly say this.state in the assignments within it. I haven't been able to set the inner class the way you or the other answers have done. I usually do another step to successfully set the state.
this.setState({
...this.state.ledge.zoom = this.state.ledge.zoom + 1,
...this.state.ledge.display = "flex",});
becomes:
var tempLedge = this.state.ledge;
tempLedge.zoom = this.state.ledge.zoom + 1;
tempLedge.display = "flex";
this.setState({ledge = tempLedge});
Related, but not a dupe:
What is the correct way of setting state variables in Reactjs and what is the difference between these approaches?
Also, check out this link for more info: State and Lifecycle
I'm trying to update state variable when button click.but my issue is,it's update once with correct data then again it updated with constructor defined data.
constructor(props) {
super(props);
this.state = {
popupshow: [{ check: false, id: '' }]
}
}
componentDidUpdate(prevProps, prevState) {
console.log("this.state.popupshow",this.state.popupshow)
}
Details(type){
this.state.popupshow[i].id = type
this.state.popupshow[i].check = true;
this.setState({ popupshow: this.state.popupshow });
}
render() {
return (
<a onClick={() => this.Details("Tv Series")}>Update </>
)
}
my console.log is like bellow
You should not update React state directly. You should always update/set React state via setState method.
These lines are against React principal
this.state.popupshow[i].id = type
this.state.popupshow[i].check = true;
Update your Details as follows
Details(type){
let { popupshow } = this.state;
let i = 0;
popupshow[i].id = type
popupshow[i].check = true;
this.setState({ popupshow });
}
Note I dont have idea of variable i so assumed that as 0
I think you should rewrite details functions like :
Details(type, i){
const popupDetail = Object.assign([], this.state.popupshow);
popupDetail[i].id = type
popupDetail[i].check = true;
this.setState({ popupshow: popupDetail });
}
you are setting popupshow: this.state.popupshow this is causing forceupdate which re renders the component hence its value gets reset.
I totally agree with the other answers have given for the question, however there are few things worth noting is you might wanna add the function to the context.
The argument in favour of adding these lines to the constructor is so that the new bound functions are only created once per instance of the class. You could also use
onClick={this.Details.bind(this, "Tv Series")}
or (ES6):
onClick={() => this.Details("Tv Series")}
but either of these methods will create a new function every time the component is re-rendered.
Then change the function to arrow fucntion too like
Details(type, i){
const popupDetail = Object.assign([], this.state.popupshow);
popupDetail[i].id = type
popupDetail[i].check = true;
this.setState({ popupshow: popupDetail });
}
I'm relatively new to React and I'm trying to change the value of one of my state properties at random once the page has rendered. But using setState in componentDidMount doesn't seem to work every time, sometimes I get the original state value returned (Which should never happen)
Is there something I'm doing wrong here;
constructor(props) {
super(props);
this.state = {
houseAd: null
};
}
and then to setState
componentDidMount() {
const houseAds = ['ad1', 'ad2'];
const rand = houseAds[Math.floor(Math.random() * houseAds.length)];
this.setState({
houseAd: rand
});
}
Sometimes I get one or the other from my houseAds array, but sometimes it just returns null
Then in my render I'm just doing something simple like;
let ad;
if (this.state.houseAd === 'ad1') {
ad = 'Ad1';
}
if (this.state.houseAd === 'ad2') {
ad = 'Ad2'
}
But obviously when the state value is null, nothing shows up
Code seems to be fine, only 1st time you will get null next time you will not get null values, check the state value using call back function after updating like this.
this.setState({
houseAd: rand
}, ()=> {console.log(this.state.houseAd});
componentDidMount is called after initial render - you probably didn't notice that - second render call is forced by setState quickly fixes/hides initial state.
console.log(this.state.houseAd) in render to proove that.
If you need sth at start - do it in constructor.
I wanted to update this variable when the condition is true, but it doesn't let me, thanks
constructor(props){
super(props);
var isActive = false;
this.props.items.map(item => (
if(item.name == this.props.product.name) {
isActive = true;
}
));
this.state = {
active: isActive
};
console.log(isActive);
this.handleClick = this.handleClick.bind(this);
}
Reason is, you forgot to use {}, If you are using any condition or wants to do some calculation use {} and put all the statement inside that. One more thing since you just want to iterate the array means not returning anything, so i that case use forEach instead of map, Use this:
this.props.items.forEach(item => { //here
if(item.name == this.props.product.name) {
isActive = true;
}
});
Check this code it will produce the same error:
[1,2,3,4].forEach(el=>(
if(el % 2 == 0)
console.log(el);
))
Check the working example:
[1,2,3,4].forEach(el=>{
if(el % 2 == 0)
console.log(el);
})
You really aren't passing an 'active' property nor state. You are trying to set a computed property, much like Ember (see How to setup Ember like computed properties in Immutablejs and Redux and Flux and React). This was considered for React and dismissed.
You should just create a function, isActive() and call it when needed. I expect you only need it when rendering a set of individual item components for which isActive is a property.
That said, there are ways of cramming this into a React codebase, but your code will be unmaintainable.
I'm new to react.js and I'm trying to math.random a number and put it in this.props.firstCard property, but it returns undefined. I tried some variables but only result is undefined or syntax error. Code:
handleClick() {
let firstCard = this.state.isFirstCardChosen;
function chooseCard() {
return Math.floor(Math.random() * (80 - 1) + 1);
}
if (firstCard == false) {
this.props.firstCard = chooseCard;
console.log(this.props.firstCard);
}
}
What's wrong with this one? Thanks in advance.
I'm going to hazard a guess and suggest that
if:
the problem isn't just one caused by the fact you are trying to mutate props (props are immutable).
and:
You're using ES2015 class syntax
then
the problem may be that your handleClick method isn't properly bound to the component state so the call to this.props returns undefined.
To solve this you can bind the handleClick in the constructor as follows:
constructor (props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
As everyone else has said the props is immutable. Also make sure you are setting props correctly and binding your handleClick function in your constructor i.e:
constructor(props) {
super(props);
his.handleClick = this.handleClick.bind(this);
}