react-sanfona icon indicating copy to clipboard operation
react-sanfona copied to clipboard

Expanded prop not overriding state on re-render?

Open robwold opened this issue 6 years ago • 1 comments

I'm trying to use the Accordion to display a list of items, and when I click on an item to expand it the body is a form that allows the user to edit that item. Each form has a 'cancel edit' button that I want to collapse the expanded form.

From my console.log statements, it looks as if when I call my resetItemsState function, my component is getting re-rendered, and all items have the isActive field set to false, so I'd expect that the element collapses, but unfortunately it seems to be remaining expanded.

import {Accordion, AccordionItem} from 'react-sanfona';
import ItemForm from './item_form';
import Button from 'react-bootstrap/Button';
import { isEqual } from 'lodash';

class EditItem extends Component {
    constructor(props){
        super(props);
        this.state = {
            items: this.props.items.slice(0)
        };
        this.addItem = this.addItem.bind(this);
        this.resetItemsState = this.resetItemsState.bind(this);
    }

    addItem(){
        const { items } = this.state;
        items.push({
            id: -1,
            name: 'New Item',
            isActive: true
        });
        this.setState({ items });
    }

    componentDidUpdate(prevProps){
        if (!isEqual(prevProps,this.props)){
            this.resetItemsState();
        }
    }

    resetItemsState(){
        console.log('cancelling edit ...');
        let items =  this.props.items.slice(0);
        items.forEach(item => {item.isActive = false} );
        console.log(JSON.stringify(items));
        this.setState({ items });
    }


    describeItem(item){
        return (
            <h4>{ item.name }</h4>
        )
    }

    render(){
        console.log('rendering edit items...')
        const {items} = this.state;
        return (
            <div>
                <h2>Item Details</h2>
                <Accordion>
                    {

                        items.map((item) => {
                            console.log(`${item.name}: ${item.isActive}`);
                            return (
                                <AccordionItem key={`item-${item.id}`} title={this.describeItem(item)} expanded={ item.isActive }>
                                    <ItemForm item={item} handleCancel={this.resetItemsState}/>
                                </AccordionItem>
                            )
                        })
                    }
                </Accordion>
                <Button onClick={this.addItem}>New Item</Button>
            </div>
        );
    }
};

export default EditItems;

The relevant part of my ItemForm component is the button

<Button type="reset" onClick={this.props.handleCancel}>Cancel</Button>

robwold avatar May 20 '19 11:05 robwold

I am seeing similar issues, were you able to find a solution?

LukeVibes avatar Jun 21 '21 12:06 LukeVibes