calling setState from onClick JavaScript function not working - reactjs

I am trying to create a button that will make visible a form to edit any contact on my list. However, when I press the button, nothing happens.
I have the initial state set to
this.state = {
contacts: [],
showEditWindow: false,
EditContactId: ''
};
I added a function:
editContact = (id) => {
this.setState({
showEditWindow: true, EditContactId: {id}
});
};
and a column:
{
title: "",
key: "action",
render: (record) => (
<button onClick={() => this.editContact(record.id)}
>
Edit
</button>
)
},
I imported EditContactModal and call it as
<EditContactModal reloadContacts={this.reloadContacts}
showEditWindow={this.state.showEditWindow}
EditContactId={this.state.EditContactId}/>
If I manually set this.state to showEditWindow:true, the window appears; however, either this.editContact(id) is not being called or it is not changing the state.
Calling this.deleteContact(id) works fine, as does setState in loadContacts() and reloadContacts()
What I am doing wrong?
Below are the full components.
Contacts.jsx
import { Table, message, Popconfirm } from "antd";
import React from "react";
import AddContactModal from "./AddContactModal";
import EditContactModal from "./EditContactModal";
class Contacts extends React.Component {
constructor(props) {
super(props);
this.state = {
contacts: [],
showEditWindow: false,
EditContactId: ''
};
this.editContact = this.editContact.bind(this);
};
columns = [
{
title: "First Name",
dataIndex: "firstname",
key: "firstname"
},
{
title: "Last Name",
dataIndex: "lastname",
key: "lastname"
},{
title: "Hebrew Name",
dataIndex: "hebrewname",
key: "hebrewname"
},{
title: "Kohen / Levi / Yisroel",
dataIndex: "kohenleviyisroel",
key: "kohenleviyisroel"
},{
title: "Frequent",
dataIndex: "frequent",
key: "frequent",
},{
title: "Do Not Bill",
dataIndex: "donotbill",
key: "donotbill"
},
{
title: "",
key: "action",
render: (record) => (
<button onClick={() => this.editContact(record.id)}
>
Edit
</button>
)
},
{
title: "",
key: "action",
render: (_text, record) => (
<Popconfirm
title="Are you sure you want to delete this contact?"
onConfirm={() => this.deleteContact(record.id)}
okText="Yes"
cancelText="No"
>
<a type="danger">
Delete{" "}
</a>
</Popconfirm>
),
},
];
componentDidMount = () => {
this.loadContacts();
}
loadContacts = () => {
const url = "http://localhost:3000/contacts";
fetch(url)
.then((data) => {
if (data.ok) {
return data.json();
}
throw new Error("Network error.");
})
.then((data) => {
data.forEach((contact) => {
const newEl = {
key: contact.id,
id: contact.id,
firstname: contact.firstname,
lastname: contact.lastname,
hebrewname: contact.hebrewname,
kohenleviyisroel: contact.kohenleviyisroel,
frequent: contact.frequent.toString(),
donotbill: contact.donotbill.toString(),
};
this.setState((prevState) => ({
contacts: [...prevState.contacts, newEl],
}));
});
})
.catch((err) => message.error("Error: " + err));
};
reloadContacts = () => {
this.setState({ contacts: [] });
this.loadContacts();
};
deleteContact = (id) => {
const url = `http://localhost:3000/contacts/${id}`;
fetch(url, {
method: "delete",
})
.then((data) => {
if (data.ok) {
this.reloadContacts();
return data.json();
}
throw new Error("Network error.");
})
.catch((err) => message.error("Error: " + err));
};
editContact = (id) => {
this.setState({
showEditWindow: true, EditContactId: {id}
});
};
render = () => {
return (
<>
<Table
className="table-striped-rows"
dataSource={this.state.contacts}
columns={this.columns}
pagination={{ pageSize: this.pageSize }}
/>
<AddContactModal reloadContacts={this.reloadContacts} />
<EditContactModal reloadContacts={this.reloadContacts}
showEditWindow={this.state.showEditWindow}
EditContactId={this.state.EditContactId}/>
</>
);
}
}
export default Contacts;
EditContactModal.jsx
import { Button, Form, Input, Modal, Select } from "antd";
import React from "react";
import ContactForm from './ContactForm';
const { Option } = Select;
class EditContactModal extends React.Component {
formRef = React.createRef();
state = {
visible: this.props.showEditWindow,
};
onFinish = (values) => {
const url = `http://localhost:3000/contacts/${this.props.EditContactId}`;
fetch(url, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(values),
})
.then((data) => {
if(data.ok) {
this.handleCancel();
return data.json();
}
throw new Error("Network error.");
})
.then(() => {
this.props.reloadContacts();
})
.catch((err) => console.error("Error: " + err))
};
showModal = () => {
this.setState({
visible: true,
});
};
handleCancel = () => {
this.setState({
visible: false,
});
};
render() {
return (
<>
{/*<Button type="primary" onClick={this.showModal}>
Create New +
</Button>*/}
<Modal
title="Edit Contact"
visible={this.state.visible}
onCancel={this.handleCancel}
footer={null}
>
<ContactForm />
</Modal>
</>
);
}
}
export default EditContactModal;

if your aim is to perform an update to the state object, you must not pass mutable data, but copy it instead into a new object.
this will allow the state changes to be picked up.
so, prefer setState({ ...state, ...someObject }) over setState(someObject).

Related

Adding a Modal Instead of "prompt" in react app

Adding a Modal Instead of "prompt" in react app
Hi Iam creating a menu builder with react-sortable-tree. I want to add a Modal when clicked on Add or Edit Task. prompt is working fine here but i want Modal to be opened. I have created state and finctions for modal but unable to render on UI when clicked. anybody help
import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.css";
import "react-sortable-tree/style.css";
import { Button } from "react-bootstrap";
import "./MenuBuilder.css";
import { Modal } from "react-responsive-modal";
import "react-responsive-modal/styles.css";
import treeData from "./MenuBuilderData";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faTrashAlt, faPlus, faPen } from "#fortawesome/free-solid-svg-icons";
import SortableTree, {
toggleExpandedForAll,
getNodeAtPath,
addNodeUnderParent,
removeNode,
changeNodeAtPath,
} from "react-sortable-tree";
const maxDepth = 5;
export default class MenuBuilder extends Component {
constructor(props) {
super(props);
this.state = {
treeData: treeData,
searchString: "",
searchFocusIndex: 0,
searchFoundCount: null,
openModal: false,
};
}
onOpenModal = (e) => {
e.preventDefault();
this.setState({ openModal: true });
};
onCloseModal = () => {
this.setState({ openModal: false });
};
handleTreeOnChange = (treeData) => {
this.setState({ treeData });
};
selectPrevMatch = () => {
const { searchFocusIndex, searchFoundCount } = this.state;
this.setState({
searchFocusIndex:
searchFocusIndex !== null
? (searchFoundCount + searchFocusIndex - 1) % searchFoundCount
: searchFoundCount - 1,
});
};
selectNextMatch = () => {
const { searchFocusIndex, searchFoundCount } = this.state;
this.setState({
searchFocusIndex:
searchFocusIndex !== null
? (searchFocusIndex + 1) % searchFoundCount
: 0,
});
};
toggleNodeExpansion = (expanded) => {
this.setState((prevState) => ({
treeData: toggleExpandedForAll({
treeData: prevState.treeData,
expanded,
}),
}));
};
getNodeKey = ({ treeIndex: number }) => {
if (number === -1) {
number = null;
}
return number;
};
handleSave = () => {
console.log(JSON.stringify(this.state.treeData));
};
editTask = (path) => {
let editedNode = getNodeAtPath({
treeData: this.state.treeData,
path: path,
getNodeKey: ({ treeIndex }) => treeIndex,
ignoreCollapsed: true,
});
let newTaskTitle = prompt("Task new name:", editedNode.node.title);
if (newTaskTitle === null) return false;
editedNode.node.title = newTaskTitle;
let newTree = changeNodeAtPath({
treeData: this.state.treeData,
path: path,
newNode: editedNode.node,
getNodeKey: ({ treeIndex }) => treeIndex,
ignoreCollapsed: true,
});
// console.log(newTree);
this.setState({ treeData: newTree });
};
addTask = (path) => {
let parentNode = getNodeAtPath({
treeData: this.state.treeData,
path: path,
getNodeKey: ({ treeIndex }) => treeIndex,
ignoreCollapsed: true,
});
let newTaskTitle = parentNode.node.children ? prompt("Task name:", "default") && prompt("form ID:", "default") : prompt("Task name:", "default") // let newFormId = prompt("Form Id:", "");
if (newTaskTitle === null) return false;
let NEW_NODE = { title: newTaskTitle };
// let NEW_ID = { id: newFormId };
let parentKey = this.getNodeKey(parentNode);
let newTree = addNodeUnderParent({
treeData: this.state.treeData,
newNode: NEW_NODE,
// newId: NEW_ID,
expandParent: true,
parentKey: parentKey,
getNodeKey: ({ treeIndex }) => treeIndex,
});
this.setState({ treeData: newTree.treeData });
};
removeTask = (path) => {
let newTree = removeNode({
treeData: this.state.treeData,
path: path,
ignoreCollapsed: true,
getNodeKey: ({ treeIndex }) => treeIndex,
});
this.setState({ treeData: newTree.treeData });
};
renderTasks = () => {
const { treeData, searchString, searchFocusIndex } = this.state;
return (
<>
<SortableTree
treeData={treeData}
onChange={this.handleTreeOnChange}
maxDepth={maxDepth}
searchQuery={searchString}
searchFocusOffset={searchFocusIndex}
canDrag={({ node }) => !node.noDragging}
canDrop={({ nextParent }) => !nextParent || !nextParent.noChildren}
searchFinishCallback={(matches) =>
this.setState({
searchFoundCount: matches.length,
searchFocusIndex:
matches.length > 0 ? searchFocusIndex % matches.length : 0,
})
}
isVirtualized={true}
generateNodeProps={(taskInfo) => ({
buttons: [
<Button
variant="link"
onClick={() => this.editTask(taskInfo.path)}
>
<FontAwesomeIcon icon={faPen} color="#28a745" />
</Button>,
<Button
variant="link"
onClick={() => this.addTask(taskInfo.path)}
>
<FontAwesomeIcon icon={faPlus} color="#007bff" />
</Button>,
<Button
variant="link"
onClick={() => this.removeTask(taskInfo.path)}
>
<FontAwesomeIcon icon={faTrashAlt} color="#dc3545" />
</Button>,
],
})}
/>
<Button style={{ width: "100px" }} onClick={this.handleSave}>
save
</Button>
</>
);
};
render() {
return (
<>
<div className="wrapper">{this.renderTasks()}</div>
{/* <div>
<button onClick={this.onOpenModal}>Click Me</button>
<Modal open={this.state.openModal} onClose={this.onCloseModal}>
<input type="text" />
</Modal>
</div> */}
</>
);
}
}
treeData.js
const treeData = [
{
expanded: true,
title: "Contact HR",
children: [
{
expanded: true,
title: "Build relationships"
},
{
expanded: true,
title: "Take a test assignment"
}
]
},
{
expanded: true,
title: "Complete a test assignment",
children: [
{
expanded: true,
title: "Send link to this doc through LinkedIn"
}
]
},
{
expanded: true,
title: "Discuss Proposal details",
children: [
{
expanded: true,
title: "Prepare list of questions."
},
{
expanded: true,
title: "Other coming soon..."
}
]
},
{
expanded: true,
title: "Make an appointment for a technical interview",
children: [
{
expanded: true,
title: "Discuss details of the technical interview"
},
{
expanded: true,
title: "Prepare to Technival Interview"
}
]
},
{
expanded: true,
title: "Accept or Decline Offer"
}
];
export default treeData;

Undefined values React

I'm trying to achieve making a suspend user button via updating the values of the user the status to Suspended, but the problem is the status is defined but other values are undefined did I do something wrong or is there any way to update the values to make the other variable like a name not required?
This is what I mean:
This is my code:
const User = (props) => (
<>
<DropdownButton id="dropdown-basic-button" title="Action">
<Dropdown.Item>
<a
href="user"
onClick={() => {
props.onSubmit(props.user[0]);
}}
>
<i className="fas fa-trash"></i> Suspend
</a>
</Dropdown.Item>
</DropdownButton>
</>
);
export default class Users extends Component {
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
this.state = { users: [] };
}
componentDidMount() {
axios
.get("http://localhost:5000/users/")
.then((response) => {
this.setState({ users: response.data });
})
.catch((error) => {
console.log(error);
});
}
onSubmit(id) {
const user = {
name: this.state.name,
password: this.state.password,
email: this.state.email,
storeName: this.state.storeName,
storeUrl: this.state.storeUrl,
date: this.state.date,
status: "Suspended",
};
console.log(user);
axios
.post("http://localhost:5000/users/update/" + id, user)
.then((res) => console.log(res.data));
}
userList(currentuser) {
return (
<User
user={currentuser}
key={currentuser[0]}
onSubmit={this.onSubmit}
/>
);
}
render() {
const columns = [
{
name: "_id",
options: {
display: false,
},
},
{
name: "name",
label: "Name",
options: {
filter: true,
sort: true,
},
},
{
name: "Action",
options: {
customBodyRender: (value, tableMeta, updateValue) => {
return <>{this.userList(tableMeta.rowData)}</>;
},
},
},
];
const { users } = this.state;
return (
<>
<MUIDataTable data={users} columns={columns} />
</>
);
}
}
You didn't define nor set the User's individual attributes' values in the state! So, no wonder they show up as undefined, when you try to read them...
The simplest solution would be:
onSubmit(id) {
//let user = this.state.users.find(user => user.id === id); // find by id
let user = this.state.users[id]; // find by index
if (user) {
user.status = 'Suspended';
console.log(user);
axios
.post("http://localhost:5000/users/update/" + id, user)
.then((res) => console.log(res.data));
}
}

How i can reload current page in react?

Here I'm fetching data with ApiClient and after that I make operation to confirm to delete the current item. My question here is how i can reload the page after I click Yes ?
type Props = {
resourceName: string,
label: string,
accessor: string,
row: Object,
}
#withRouter
#connectAPI((apiClient: ApiClient, props: Props) => ({
deleteObject: {
send: (id: any) => apiClient.resources[props.resourceName].delete(id),
success: () => {
// TODO: ?
},
},
}))
class DeleteComponent extends React.Component<Props> {
state = {
open: false,
};
handleOpen = () => {
this.setState({ open: true });
};
handleConfirm = (props: Props) => {
const { accessor, row, deleteObject } = props;
const id = row._original[accessor];
deleteObject({
id,
});
};
render(): React.ReactNode {
const { open } = this.state;
let message = null;
if (open) {
message = (
<MessageDialog
message="Are tou sure you want to delete ?"
actions={{
yes: {
label: 'Yes',
callback: this.handleConfirm,
},
no: {
label: 'No',
callback: (e: SyntheticMouseEvent<HTMLButtonElement>) => this.setState({ open: false }),
},
}}
/>
);
}
return (
<React.Fragment>
<Button
position="right"
onClick={this.handleOpen}
hoverIndicator="light-1"
/>
{message}
</React.Fragment>
);
}
}
export default DeleteComponent;

How to do search in table?

I want to search with all the pagination and sorter field on place.
That is i want to call handleChange with searchkeyword.
So how can i call handleSearch and than call handleChange from within handleSearch?
import React from "react";
import { withRouter } from "react-router-dom";
import { Table, Button, Icon, Row, Col, Input } from "antd";
import axios from "axios";
const Search = Input.Search;
class App extends React.Component {
state = {
data: [],
searchValue: "",
loading: false,
visible: false,
pagination: {}
};
componentDidMount() {
this.fetch();
}
handleTableChange = (pagination, filter, sorter, value) => {
console.log(pagination, value, sorter, "Table Change");
let sorterOrder = "";
let sorterField = "";
let searchVal = "";
const pager = { ...this.state.pagination };
pager.current = pagination.current;
this.setState({
pagination: pager
});
if (value) {
console.log("inside if");
searchVal = undefined;
} else {
console.log("inside else");
searchVal = value;
}
if (sorter) {
if (sorter.order === "ascend") {
sorterOrder = "ASC";
}
if (sorter.order === "descend") {
sorterOrder = "DESC";
}
sorterField = sorter.field;
}
this.fetch({
page: pagination.current,
sortField: sorterField,
sortOrder: sorterOrder,
...filter,
value: searchVal
});
};
fetch = (params = {}) => {
this.setState({ loading: true });
axios.post("***/****", params).then(res => {
const pagination = { ...this.state.pagination };
let apiData = res.data.result;
if (res.data.status === 1) {
const objects = apiData.map(row => ({
key: row.id,
id: row.id,
firstName: row.firstName,
lastName: row.lastName,
status: row.status,
email: row.email
}));
console.log(res.data);
pagination.total = res.data.count;
this.setState({
loading: false,
data: objects,
pagination
});
} else {
console.log("Database status is not 1!");
}
});
};
handleSearch = value => {
console.log("value", value);
this.setState({
searchValue: value
});
let searchkey = this.state.searchValue;
const pagination = { ...this.state.pagination };
const sorter = { ...this.state.sorter };
console.log("search", value, pagination, sorter);
this.handleTableChange({
value
});
};
render() {
const columns = [
{
title: "First Name",
dataIndex: "firstName",
sorter: true
},
{
title: "Email",
dataIndex: "email",
sorter: true
}
];
return (
<div>
<Search
placeholder="input search text"
className="searchBut"
onSearch={value => this.handleSearch(value)}
/>
<Button
className="addBut"
style={{ marginTop: "0" }}
type="primary"
onClick={() => this.openForm()}
>
+ Add Admin
</Button>
</div>
<Table
bordered
columns={columns}
dataSource={this.state.data}
pagination={{ total: this.state.pagination.total, pageSize: 4 }}
loading={this.state.loading}
onChange={this.handleTableChange}
/>
);
}
}
export default withRouter(App);
here when i give value in search field it will call post request with request payload as follows:
{sortField: "", sortOrder: ""}
sortField: ""
sortOrder: ""
So how can i do that?
I'm not sure what you trying of achieve it here.
But you can always filter the source data of the table. Like following
<Table
bordered
columns={columns}
dataSource={this.state.data.filter(data=> Object.keys(data).filter(key => data[key].includes(searchValue)).length > 0 ? true: false)}
pagination={{ total: this.state.pagination.total, pageSize: 4 }}
loading={this.state.loading}
onChange={this.handleTableChange}
/>
let me know if it helps.

Reactjs: How to properly fetch each users record from database on pop button click using Reactjs

The code below shows each user info on users list button click.
Now I want fetch each users record from database on users list button click.
In the open() function, I have implemented the code below
open = (id,name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: 'id',
uname: 'name'
};
this.setState({ loading_image: true }, () => {
axios.post("http://localhost/data.php", { user_data })
.then(response => {
this.setState({
chatData1: response.data[0].id,
chatData: response.data,
loading_image: false
});
console.log(this.state.chatData);
alert(this.state.chatData1);
})
.catch(error => {
console.log(error);
});
});
}
In class OpenedUser(), I have initialize in the constructor the code below
chatData: []
In the render method have implemented the code
<b> Load Message from Database for each user ({this.state.chatData1})</b>
<div>
{this.state.chatData.map((pere, i) => (<li key={i}>{pere.lastname} - {pere.id}----- {pere.username}</li>))}
</div>
Here is my Issue:
My problem is that the Axios Api is getting the result but am not seeing any result in the render method.
but I can see it in the console as per code below
Array(1)
0: {id: "1", firstname: "faco", lastname: "facoyo"}
length: 1
Here is an example of json api response.
[{"id":"1","firstname":"faco","lastname":"facoyo"}]
Here is the full code
import React, { Component, Fragment } from "react";
import { render } from "react-dom";
import { Link } from 'react-router-dom';
import axios from 'axios';
class User extends React.Component {
open = () => this.props.open(this.props.data.id, this.props.data.name);
render() {
return (
<React.Fragment>
<div key={this.props.data.id}>
<button onClick={() => this.open(this.props.data.id,this.props.data.name)}>{this.props.data.name}</button>
</div>
</React.Fragment>
);
}
}
class OpenedUser extends React.Component {
constructor(props) {
super(props);
this.state = {
chatData: [],
hidden: false,
};
}
componentDidMount(){
} // close component didmount
toggleHidden = () =>
this.setState(prevState => ({ hidden: !prevState.hidden }));
close = () => this.props.close(this.props.data.id);
render() {
return (
<div key={this.props.data.id} style={{ display: "inline-block" }}>
<div className="msg_head">
<button onClick={this.close}>close</button>
<div>user {this.props.data.id}</div>
<div>name {this.props.data.name}</div>
{this.state.hidden ? null : (
<div className="msg_wrap">
<div className="msg_body">Message will appear here</div>
<b> Load Message from Database for each user ({this.state.chatData1}) </b>
<div>
{this.state.chatData.map((pere, i) => (
<li key={i}>
{pere.lastname} - {pere.id}----- {pere.username}
</li>
))}
</div>
</div>
)}
</div>
</div>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
shown: true,
activeIds: [],
data: [
{ id: 1, name: "user 1" },
{ id: 2, name: "user 2" },
{ id: 3, name: "user 3" },
{ id: 4, name: "user 4" },
{ id: 5, name: "user 5" }
],
};
}
toggle() {
this.setState({
shown: !this.state.shown
});
}
open = (id,name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: 'id',
uname: 'name'
};
this.setState({ loading_image: true }, () => {
axios.post("http://localhost/apidb_react/search_data.php", { user_data })
.then(response => {
this.setState({
chatData1: response.data[0].id,
chatData: response.data,
loading_image: false
});
console.log(this.state.chatData);
alert(this.state.chatData1);
})
.catch(error => {
console.log(error);
});
});
// end axios api call
this.setState((prevState) => ({
activeIds: prevState.activeIds.find((user) => user === id)
? prevState.activeIds
: [...prevState.activeIds, id]
}));
}
close = id => {
this.setState((prevState) => ({
activeIds: prevState.activeIds.filter((user) => user !== id),
}));
};
renderUser = (id) => {
const user = this.state.data.find((user) => user.id === id);
if (!user) {
return null;
}
return (
<OpenedUser key={user.id} data={user} close={this.close}/>
)
}
renderActiveUser = () => {
return (
<div style={{ position: "fixed", bottom: 0, right: 0 }}>
{this.state.activeIds.map((id) => this.renderUser(id)) }
</div>
);
};
render() {
return (
<div>
{this.state.data.map(person => (
<User key={person.id} data={person} open={this.open} />
))}
{this.state.activeIds.length !== 0 && this.renderActiveUser()}
</div>
);
}
}
The problem is you're making the request in the App component and storing in state but you're trying to access the state in a child component so it will never actually read the data.
To fix this you need to pass in the chat data via prop
<OpenedUser
chatData={this.state.chatData}
key={user.id}
data={user}
close={this.close}
/>
Note: In my runnable example, I've replaced your api endpoint with a mock api promise.
const mockApi = () => {
return new Promise((resolve, reject) => {
const json = [{ id: "1", firstname: "faco", lastname: "facoyo" }];
resolve(json);
});
};
class User extends React.Component {
open = () => this.props.open(this.props.data.id, this.props.data.name);
render() {
return (
<React.Fragment>
<div key={this.props.data.id}>
<button
onClick={() => this.open(this.props.data.id, this.props.data.name)}
>
{this.props.data.name}
</button>
</div>
</React.Fragment>
);
}
}
class OpenedUser extends React.Component {
constructor(props) {
super(props);
this.state = {
hidden: false
};
}
componentDidMount() {} // close component didmount
toggleHidden = () =>
this.setState(prevState => ({ hidden: !prevState.hidden }));
close = () => this.props.close(this.props.data.id);
render() {
return (
<div key={this.props.data.id} style={{ display: "inline-block" }}>
<div className="msg_head">
<button onClick={this.close}>close</button>
<div>user {this.props.data.id}</div>
<div>name {this.props.data.name}</div>
{this.state.hidden ? null : (
<div className="msg_wrap">
<div className="msg_body">Message will appear here</div>
<b>
{" "}
Load Message from Database for each user ({this.state.chatData1}
){" "}
</b>
<ul>
{this.props.chatData.map((pere, i) => (
<li key={i}>
{pere.lastname} - {pere.id}----- {pere.username}
</li>
))}
</ul>
</div>
)}
</div>
</div>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
shown: true,
chatData: [],
activeIds: [],
data: [
{ id: 1, name: "user 1" },
{ id: 2, name: "user 2" },
{ id: 3, name: "user 3" },
{ id: 4, name: "user 4" },
{ id: 5, name: "user 5" }
]
};
}
toggle() {
this.setState({
shown: !this.state.shown
});
}
open = (id, name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: "id",
uname: "name"
};
// this.setState({ loading_image: true }, () => {
// axios
// .post("http://localhost/apidb_react/search_data.php", { user_data })
// .then(response => {
// this.setState({
// chatData1: response.data[0].id,
// chatData: response.data,
// loading_image: false
// });
// console.log(this.state.chatData);
// alert(this.state.chatData1);
// })
// .catch(error => {
// console.log(error);
// });
// });
this.setState({ loading_image: true }, () => {
mockApi().then(data => {
this.setState({
chatData1: data[0].id,
chatData: data,
loading_image: false
});
});
});
// end axios api call
this.setState(prevState => ({
activeIds: prevState.activeIds.find(user => user === id)
? prevState.activeIds
: [...prevState.activeIds, id]
}));
};
close = id => {
this.setState(prevState => ({
activeIds: prevState.activeIds.filter(user => user !== id)
}));
};
renderUser = id => {
const user = this.state.data.find(user => user.id === id);
if (!user) {
return null;
}
return (
<OpenedUser
chatData={this.state.chatData}
key={user.id}
data={user}
close={this.close}
/>
);
};
renderActiveUser = () => {
return (
<div style={{ position: "fixed", bottom: 0, right: 0 }}>
{this.state.activeIds.map(id => this.renderUser(id))}
</div>
);
};
render() {
return (
<div>
{this.state.data.map(person => (
<User key={person.id} data={person} open={this.open} />
))}
{this.state.activeIds.length !== 0 && this.renderActiveUser()}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I see a few missing points in your code namely you are using li without ul which is a kind of invalid markup, then you have mapping for .username which is undefined field according to response which may also throw error.

Resources