Solution 1 :

you need to track the visible state of the PersonModal in the PersonList component. You should have a boolean variable to control the visibility of the PersonModal.

and the PersonModal will not control its visiblity state, rather it will get it from its clients , in your case the client is PersonList. so lets begin with the code

first, edit the PersonModal component to expect props from its clients

class PersonModal extends React.Component {
    // handleOk (...)
    // handleCancel (...)

    handleCancel = () => {

        // because the client controls the visivlity state of the component
        this.props.hideModal();
    }

    render() {
         /// this.props.isVisible is required, and it will be a boolean true or false.
        const shouldBeVisible = this.props.isVisible;

        return <Modal
            title="Basic Modal"
            visible={shouldBeVisible}
            onOk={this.handleOk}
            onCancel={this.handleCancel}
        >
            Modal body
        </Modal>
    }
}
export default PersonModal;

so now your PersonModal component expexts a prop; which is isVisible prop.


class PersonList extends React.Component {

    state = {
        // the client controls the visibility of the modal with this state key;
        showModal: false,
        personId: null
    }


    // edited
    showModal = (personId) => {
       // set state to update the UI and show the PersonModal
        this.setState({
            showModal: true,
            personId: personId
        });
    }

     hideModal= () => this.setState({showModal: false});

    render() {
        const persons = this.props.list;
        return (
            <div>
             // now PersonModal will only be visible when the parent of it tells it to
            <PersonModal 
            isVisible = {this.state.showModal} 
                hideModal= {this.hideModal}
/>   
            <List
                itemLayout="horizontal"
                dataSource={persons}
                renderItem={item => (
                    <>
                    <List.Item onClick={() => this.showModal(123)} style={{cursor: 'pointer'}}>
                        <List.Item.Meta
                            avatar={<Avatar src="avatar.png"/>}
                            title={<span>{item.firstName} {item.lastName}</span>}
                            description={<span>{item.city}, {item.country}</span>}
                        />
                    </List.Item>
                    </>
                )}
            />
            </div>
        );
    }
}

hope it helps you;

this is how the problem is approached in the React world

Solution 2 :

Your onClick handlers are being called continuously. Change them to functions that return the function you wish to call and this should fix your issue.

So,

  • Instead of: <List.Item onClick={{this.showModal(123)} style={{cursor: 'pointer'}}>
  • We do: <List.Item onClick={() => {this.showModal(123)} } style={{cursor: 'pointer'}}>

updated stackblitz here

Problem :

I have a PersonList component, wherever user clicks on List.Item I want to pass some details like personId to PersonModal and display it. I’m using Ant Design component for modal.

Below is what I tried, but unfortunately I’m getting an error like:

Warning: Can’t call setState on a component that is not yet mounted.
This is a no-op, but it might indicate a bug in your application.
Instead, assign to this.state directly or define a state = {};
class property with the desired state in the PersonModal component.

PersonModal.js

import React from "react";
import {Modal} from "antd";

class PersonModal extends React.Component {
    constructor(props) {
        super(props);
        console.log(this.props.personId)
    }

    state = { visible: false };

    showModal = () => {
        this.setState({
            visible: true,
        });
    };

    // handleOk (...)
    // handleCancel (...)

    render() {
        return <Modal
            title="Basic Modal"
            visible={this.state.visible}
            onOk={this.handleOk}
            onCancel={this.handleCancel}
        >
            Modal body
        </Modal>
    }
}
export default PersonModal;

PersonList.js

import React from "react";
import {Icon, Input, List, Avatar} from "antd";
import PersonModal from "PersonModal/PersonModal"

class PersonList extends React.Component {

    showModal(personId) {
        const modal = new PersonModal({personId: 123})
        modal.showModal()
    }

    render() {
        const persons = this.props.list;
        return (
            <div>
            <List
                itemLayout="horizontal"
                dataSource={persons}
                renderItem={item => (
                    <>
                    <List.Item onClick={this.showModal(123)} style={{cursor: 'pointer'}}>
                        <List.Item.Meta
                            avatar={<Avatar src="avatar.png"/>}
                            title={<span>{item.firstName} {item.lastName}</span>}
                            description={<span>{item.city}, {item.country}</span>}
                        />
                    </List.Item>
                    </>
                )}
            />
            </div>
        );
    }
}

What would be correct way of approaching this problem? Since I am new to React i suppose this is not a correct approach.

Reproduced issue on stackblitz here

Comments

Comment posted by Akber Iqbal

if you share a working stackblitz which replicates this issue, it’l be much easier to help

Comment posted by stackblitz

@AkberIqbal Based on answer below and current issue I prepared

Comment posted by stackblitz.com/edit/react-7phgq2?file=PersonList.js

please check forked version without error at

Comment posted by Tomasz

Thank you @AkberIqbal looks like same moment I realised that it has to be an arrow function inside

Comment posted by Akber Iqbal

Now you’ll always remember this when you come across this error 🙂 – would appreciate if you accept the answer…

Comment posted by Tomasz

Thank you for your explanation. I tried to use the code from your examples but unfortunately got some errors:

Comment posted by Osama Abdullah

sorry my bad, i edited the showModal function , check that out

Comment posted by Tomasz

I actually copy-pasted all your code, but unfortunately I’m getting still same error

Comment posted by Osama Abdullah

what about your handleOk function, how did you write it

Comment posted by Osama Abdullah

make that an arrow function too, like this, handleOk = () => { /// };

By