Boris Civcic
Boris Civcic

Reputation: 110

How to show currently state on click

How to show currently update state.

I have onClick function <span onClick={() => { this.toggleCollapse(i, info) }}><img src={Arrow_Down} alt='Arrow' /></span> to toggle card. But I have a problem because card it's opened on a second click. On first click my state showCards: [] empty.

I want to update this array in state

{title: "title3", description: "Sed non urna. Donec et ante. Phasellus eu ligula. … dolor at aliquet laoreet, mauris turpis porttito", open: "inactive"}description: "Donec et ante. Phasellus eu ligula. Vestibulum sit amet purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttito"open: "inactive"title: "title3"__proto__: Object iiiii 6

But just last object open if it's active to be inactive.

I have that function but does not work very well.

Here you go my component

import React, { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import Header from '../../common/Header/'
import Masonry from '../../common/Masonry/'
import { cardAction } from '../../store/actions/Cards'
import Arrow_Down from '../../assets/img/arrow-down.svg'

class Dashboard extends Component {

  componentDidMount() {
    this.props.cardAction()
  }
  constructor(props) {
    super(props)
    this.state = {
      collapsed: true,
      class: 'collapsed',
      showCards: []
    }
    this.toggleCollapse = this.toggleCollapse.bind(this);
  }

  toggleCollapse(i, info) {
    console.log('i', info, 'iiiii', i)
    this.setState({
      collapsed: !this.state.collapsed,
      class: this.state.collapsed ? '' : 'collapsed',
      showCards: info
    });
    // this.setState(prevState => {
    //   return { showCards: !prevState.info };
    // });
    if (this.state.showCards.open === 'active') {
      this.state.showCards['open'] = 'inactive'
      console.log('open')
    }
    else {
      this.state.showCards['open'] = 'active'
      console.log('close')
    }
    console.log('showwww', this.state.showCards)
  }

  render() {
    const cardList = this.props.Cards.map((info, i) => {
      return (
        <div className={(info.open === 'active') ? 'collapsed' : ''} key={i}>
          <div className={(info.open === 'active') ? 'header flex space-between active' : 'header flex space-between'}>
            <h2>{info.title}</h2>
            <span onClick={() => { this.toggleCollapse(i, info) }}><img src={Arrow_Down} alt='Arrow' /></span>
          </div>
          <div className='content'>
            <p>{info.description}</p>
          </div>
        </div>
      )
    })
    return (
      <div>
        <Header />
        <Masonry columns={3} gap={20}>
          {cardList}
        </Masonry>
      </div>
    )
  }
}

Dashboard.defaultProps = {
  columns: 2,
  gap: 20,
  Cards: []
}
Dashboard.propTypes = {
  Cards: PropTypes.array.isRequired,
}

const mapStateToProps = state => {
  return { Cards: state.cards.result }
}

const mapDispatchToProps = dispatch => ({
  cardAction: () => dispatch(cardAction())
})
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard)

EDIT:

import React, { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import Header from '../../common/Header/'
import Masonry from '../../common/Masonry/'
import { cardAction } from '../../store/actions/Cards'
import Arrow_Down from '../../assets/img/arrow-down.svg'

class Dashboard extends Component {

  componentDidMount() {
    this.props.cardAction()
  }
  constructor(props) {
    super(props)
    this.state = {
      collapsed: true,
      class: 'collapsed',
      showCards: []
    }
    this.toggleCollapse = this.toggleCollapse.bind(this);
  }

  toggleCollapse(i, info) {
    console.log('i', info, 'iiiii', i)
    this.setState({
      ollapsed: !this.state.collapsed,
      class: this.state.collapsed ? '' : 'collapsed',
      showCards: info
    }, () => {
      // my state is updated here !
      console.log('llllll', this.state.showCards.open)
      if (this.state.showCards.open === 'active') {
        console.log('open')
        this.setState({
          showCards: {
            open: 'inactive',
            ...this.state.showCards
          }
        })
      }
      else if (this.state.showCards.open === 'inactive') {
        this.setState({
          showCards: {
            open: 'active',
            ...this.state.showCards
          }
        })
      }
      // console.log('this state', this.state)
    })
  }

  render() {
    const cardList = this.props.Cards.map((info, i) => {
      return (
        <div className={(info.open === 'active') ? 'collapsed' : ''} key={i}>
          <div className={(info.open === 'active') ? 'header flex space-between active' : 'header flex space-between'}>
            <h2>{info.title}</h2>
            <span onClick={() => { this.toggleCollapse(i, info) }}><img src={Arrow_Down} alt='Arrow' /></span>
          </div>
          <div className='content'>
            <p>{info.description}</p>
          </div>
        </div>
      )
    })
    return (
      <div>
        <Header />
        <Masonry columns={3} gap={20}>
          {cardList}
        </Masonry>
      </div>
    )
  }
}

Dashboard.defaultProps = {
  columns: 2,
  gap: 20,
  Cards: []
}
Dashboard.propTypes = {
  Cards: PropTypes.array.isRequired,
}

const mapStateToProps = state => {
  return { Cards: state.cards.result }
}

const mapDispatchToProps = dispatch => ({
  cardAction: () => dispatch(cardAction())
})
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard)

Upvotes: 0

Views: 365

Answers (1)

Pierre C.
Pierre C.

Reputation: 1430

The first thing to understand is that setState is asynchronous (see React.Component#setState). This means that the state of your component does not update immediately after the call to setState.

But setState accepts a callback function where you can put the code that needs the updated state.

this.setState({ ... }, () => {
    // my state is updated here !
});

As pointed out by Amir Saleem, updating the state without using setState is not the right way to do it.

this.state.showCards['open'] = 'active'

should be

this.setState({
    showCards: {
        open: 'active',
        ...this.state.showCards
    }
});

Upvotes: 1

Related Questions