Crispen Smith
Crispen Smith

Reputation: 533

React State vs. Props - Why are state changes not reflected in components?

I'm trying to create a div that sits underneath the main app (lexically) but is styled to only show up after a timed delay. I feel like this is most likely a very simple failure on my part to grasp some of the react concepts I'm working with.

Here's my code: (The CSS is pseudo code)

import React, {Component} from 'React'; //eslint-disable-line
import styled from 'styled-components';
import ReactTimeout from 'react-timeout';

const Icon = styled.div.attrs({
  dataRight: props => props.dataRight || '1em',
  dataLeft: props => props.dataLeft || '1em',
  displayIcons: props => props.displayIcons|| 'none'

})`
    display: ${props => props.displayIcons};
    font-size: 1.5rem;
    background-color: rebeccapurple;
    position: absolute;
    top: 1rem;
    right: ${props => props.dataRight};
    left: ${props => props.dataLeft};
`;



class Iconset extends Component {

  constructor(props) {
    super(props);
    this.state = {
      displayIcons: 'none'
    };
  }

  componentDidMount () {
    this.props.setTimeout(this.showIcons, 4000);
    alert('Display Icons =  ' + this.state.displayIcons);
  }

  showIcons() {  
    this.setState({displayIcons: 'Block'}); 
    alert('Display Icons =  ' + this.state.displayIcons);
  }   

  render () {
    return ( 
      <div id='iconset'>
        <Icon dataLeft="auto" dataRight="1em" display={this.props.displayIcons}>First Icon</Icon> {/*eslint-disable-line */}
        <Icon dataLeft="1em" dataRight="auto" display={this.props.displayIcons}>Second Icon</Icon> {/*eslint-disable-line */}
      </div>
    );
  }
}
export default ReactTimeout(Iconset);

So, my current understanding is that when the timeout fires the container state change should populate down to the children and override the display: none with display: block. That change never seems to happen although the state-change itself does happen.

What concept am I missing here?

Upvotes: 0

Views: 802

Answers (2)

user5602665
user5602665

Reputation:

When you use setState, you're setting the displayIcons variable in component's internal state which would be accessed by this.state.displayIcons.

If you look at your render, in the display prop, you're targeting this.props.displayIcons

You would only use props here if you were changing the displayIcons property in a parent component.

Change that to this.state.displayIcons and it should work as you expect.

Upvotes: 1

karran
karran

Reputation: 314

I'm not sure what makes sense or not to your code.

this.props.setTimeout(this.showIcons, 4000);

Is setTimeout really a props function? It looks like that what you really want was to just call setTimeOut:

setTimeout(this.showIcons, 4000);

Why are you rendering props.displayIcons ?

<Icon dataLeft="auto" dataRight="1em" display={this.props.displayIcons}>First Icon</Icon> {/*eslint-disable-line */}
<Icon dataLeft="1em" dataRight="auto" display={this.props.displayIcons}>Second Icon</Icon> {/*eslint-disable-line */}

I believe what you really want is to render the state that you changed on timeOut:

<Icon dataLeft="auto" dataRight="1em" display={this.state.displayIcons}>First Icon</Icon> {/*eslint-disable-line */}
<Icon dataLeft="1em" dataRight="auto" display={this.state.displayIcons}>Second Icon</Icon> {/*eslint-disable-line */}

Hope that helps!

Upvotes: 0

Related Questions