Reputation: 110
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
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