How to let React select component so extend its parent - javascript

I'm using react-select for a drop down menu looking like this
component looks like this :
<table className="w-full text-sm text-center text-projectlightblack overflow-hidden font-poppins my-10 border-t border-t-projectblue border-l border-l-projectblue ">
<thead className="text-xl bg-projectbackgroundgray text-projectlightblack font-medium"></thead>
<tbody className="font-normal text-lg whitespace-pre-line text-start px-[10px] ">
{data?.rows?.map((row, index) => {
return (
<tr
className="py-[10px] border-b border-b-projectblue border-r border-r-projectblue border-t-0 border-l-0"
key={index}
>
{row?.map((cell, index) => {
let {
value,
tailwindClasses,
cellType,
dataType,
address,
options,
} = processCell(cell, cellData) || {};
if (cellType == "input" && dataType == "list") {
return (
<td className="w-[300px] h-auto" key={index}>
{isLoading || isFetching ? (
<InputLoadingIndicator />
) : (
<Select
options={options}
isLoading={isLoading || isFetching}
value={value}
onChange={(option) => {
setQueryKey(option);
mutate({
addressValue: address,
dateValue: option.value,
});
}}
styles={{
control: (baseStyles, state) => ({
...baseStyles,
borderColor: state.isFocused ? "white" : "white",
}),
}}
menuPlacement="auto"
/>
)}
</td>
);
}
basically when I extend the dropdown menu and it's bigger than parent component it doesn't work , giving a fixed height to the table tag would fix it but it's a reusable component and that's ruin it , Any other fixes?

Related

Disclosure Panel closes when component re-renders

I am creating a nested sortable list in react using the dnd package. Each item inside the draggable contains input fields wrapped inside the Disclosure component from #headlessui. I am updating the item value with onChange on each input field.
The item field is updating on every input but the problem is disclosure panel closes immediately on keystroke. The issue is probably due to rerendering the list I simply tried making a list of the Disclosure panels without dnd and it doesn't close the Disclosure panel on input.
I have reproduced the issue in repl.it sample and I think it's too long to post code here.
export default function App() {
const [items, setItems] = useState([
{id: 1, title: 'My Item 1'},
{id: 2, title: 'My Item 2'},
{id: 3, title: 'My Item 3'},
{id: 4, title: 'My Item 4'},
]);
const handleInputChange = (e, item) => {
const {name, value} = event.target;
setItems(prev =>
[
...prev.map((elm) => {
if (elm.id === item.id) {
elm[name] = value;
}
return elm;
})
]
)
}
return (
<main>
<SortableTree
items={items}
onItemsChanged={setItems}
TreeItemComponent={forwardRef((props, ref) => {
return (
<SimpleTreeItemWrapper
{...props}
showDragHandle={false}
disableCollapseOnItemClick={true}
hideCollapseButton={true}
indentationWidth={20}
ref={ref}
className={"w-[400px]"}
>
<Disclosure as="div" className={"w-full mb-2"}>
{({ open }) => (
<>
<Disclosure.Button
open={true}
className="flex items-center w-full justify-between bg-[#F6F7F7] border border-gray-200 px-3 py-2 text-left text-xs font-medium text-gray-600 shadow-sm hover:border-gray-400 focus:outline-none focus-visible:ring focus-visible:ring-purple-500 focus-visible:ring-opacity-75"
>
<span>{props.item.title}</span>
<ChevronUpIcon
className={`${
open ? "rotate-180 transform" : ""
} h-5 w-5 text-gray-500`}
/>
</Disclosure.Button>
<Disclosure.Panel className="px-4 pt-4 pb-2 text-sm text-gray-500">
<div className="flex flex-col mb-2">
<label
htmlFor="nav_label"
className="text-xs mb-1"
>
Navigation Label
</label>
<input
onChange={(e) => handleInputChange(e, props.item)}
name='title'
type={"text"}
className="px-2 py-1 border border-gray-400"
value={props.item.title}
/>
</div>
<div className="">
<button
className="text-red-500 text-xs"
>
Remove
</button>
</div>
</Disclosure.Panel>
</>
)}
</Disclosure>
</SimpleTreeItemWrapper>
);
})}
/>
</main>
)
}

Multiple refs on react dnd

How can I use multiple refs on react beautiful dnd libray
<Droppable droppableId={column.id} isDropDisabled={Boolean(pastDays && !presentDay)}>
{(provided) => (
<div
className={classNames(styles.events, {[styles.smallEvents] : events.length > 2})}
ref={provided.innerRef}
style={{height: '100%' }}
{...provided.droppableProps}
> {events.map((event, index) => {
const dragDisabled = Boolean(pastDays && !presentDay)
return <Draggable key={event.id} draggableId={event.id} index={index} isDragDisabled={dragDisabled}>
{(provided) => {
const style = {
backgroundColor: 'red',
height: styleHeight,
...provided.draggableProps.style
};
return (
<div ref={provided.innerRef, ref}
{...provided.dragHandleProps}
{...provided.draggableProps}
style={style}
className={classNames(styles.largeEvent,
{ [styles.smallEvent]: events.length > 2 },
{ [styles.hide]: index >= 7 })}>
<MonthlyEvent eventImageSrc={event.eventImageSrc} channel={event.channel} />
</div>
)
}}
</Draggable>
})}
{provided.placeholder}
<div className={classNames(styles.more, { [styles.show] : events.length > 7 })}>
<span className={styles.moreAdd}>+ {events.length - 7}</span>
</div>
</div>
)}
</Droppable>
So I have const ref = useRef(null) and when
I pass ref={provided.innerRef, ref} does not work the drag is broken

document.location.pathname updating when routing from class component to functional component in react-router

These are the routes:
const routes = [
{ url: "", component: Home }, //class
{ url: "doctors", component: Doctors }, //class
{ url: "activedevices", component: ActiveDevices }, //functional
{ url: "nurses", component: Nurse }, //functional
{ url: "patients", component: PatientTable }, //functional
{ url: "floor-management", component: FloorManagement }, //class
{ url: "organizations", component: Organizations }, //functional
]
<Switch>
{routes.map((data, i) => (
<Route
key={i}
exact
path={`/${data.url}`}
component={data.component}
/>
))}
<Route path="*" component={()=> <Redirect to='/' />} />
</Switch>
I'm using window.location.pathname to determine the current path and highlight the corresponding menu item.
Dashboard
Patients
Floor Management
It is working fine when I try to navigate between class to class component or class to functional component. But when I try functional to functional component, the window.document.pathname does not update which results in respective menu item not being highlighted and last one remain highlighed. But the routing still works, I'm routed to the clicked routes and it also shows updated route in the address bar but not inside the script.
These are images showing updates routes in address bar but not in pathname:
Nurses
Active Devices
Here is the code for a functional component:
import React, { useState, useRef, useEffect } from "react";
import { Table, Pagination, Badge, Dropdown } from "react-bootstrap";
import { Link } from "react-router-dom";
import ActiveDevicesRow from "./ActiveDeviceRow";
import {baseURL, API, BEARER_TOKEN} from '../../../config'
const ActiveDevices = () => {
const [activeDevices, setActiveDevices] = useState(null)
let serial=1;
var myHeaders = new Headers();
myHeaders.append("Authorization", BEARER_TOKEN);
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
async function getActiveDevices(){
await fetch(baseURL+API.DEVICES, requestOptions)
.then(res => res.json())
.then(res => {
if(Array.isArray(res)) setActiveDevices(res)
})
.catch(err => console.log(err))
// console.log(activeDevices)
}
useEffect(()=>{
getActiveDevices()
}, [])
const [data, setData] = useState(
document.querySelectorAll("#ActiveDevices_basic_table tbody tr")
);
const sort = 5;
const activePag = useRef(0);
const [test, settest] = useState(0);
// Active data
const chageData = (frist, sec) => {
for (var i = 0; i < data.length; ++i) {
if (i >= frist && i < sec) {
data[i].classList.remove("d-none");
} else {
data[i].classList.add("d-none");
}
}
};
// use effect
useEffect(() => {
setData(document.querySelectorAll("#ActiveDevices_basic_table tbody tr"));
}, [test]);
// Active pagginarion
activePag.current === 0 && chageData(0, sort);
// paggination
let paggination = Array(Math.ceil(data.length / sort))
.fill()
.map((_, i) => i + 1);
// Active paggination & chage data
const onClick = (i) => {
activePag.current = i;
chageData(activePag.current * sort, (activePag.current + 1) * sort);
settest(i);
};
// console.log(document.querySelectorAll(".sorting_1 input")[0].checked);
return (
<div className="col-12">
<div className="card">
<div className="card-header">
<h4 className="card-title">Active Devices</h4>
</div>
<div className="card-body">
<Table responsive className="w-100">
<div
id="ActiveDevices_basic_table"
className="dataTables_wrapper"
>
<table
id="example5"
className="display dataTable no-footer w-100"
style={{ minWidth: 845 }}
role="grid"
aria-describedby="example5_info"
>
<thead>
<tr role="row">
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Patient ID: activate to sort column ascending"
style={{ width: 73 }}
>
S.R. No.
</th>
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Date Check in: activate to sort column ascending"
style={{ width: 100 }}
>
ID
</th>
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Patient Name: activate to sort column ascending"
style={{ width: 100 }}
>
Name
</th>
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Doctor Assgined: activate to sort column ascending"
style={{ width: 120 }}
>
Serial
</th>
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Disease: activate to sort column ascending"
style={{ width: 62 }}
>
DeviceType
</th>
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Action: activate to sort column ascending"
style={{ width: 47 }}
>
State
</th>
</tr>
</thead>
<tbody>
{activeDevices && activeDevices.length !== 0 ? activeDevices.map((device, index)=>
<ActiveDevicesRow
key={'device'+device.id}
srNo={serial++}
id={device.id}
serial={device.serial}
name={device.name}
deviceStatus={device.isActive}
deviceType={device.deviceType}
onClick=""
/>
)
: <tr><td colSpan='7' style={{textAlign:'center'}}>No Data Available</td></tr>
}
</tbody>
</table>
<div className="d-flex justify-content-between align-items-center mt-3">
<div className="dataTables_info">
Showing {activePag.current * sort + 1} to{" "}
{data.length > (activePag.current + 1) * sort
? (activePag.current + 1) * sort
: data.length}{" "}
of {data.length} entries
</div>
<div
className="dataTables_paginate paging_simple_numbers"
id="example5_paginate"
>
<Link
className="paginate_button previous disabled"
to="#"
onClick={() =>
activePag.current > 0 &&
onClick(activePag.current - 1)
}
>
Previous
</Link>
<span>
{paggination.map((number, i) => (
<Link
key={i}
to="#"
className={`paginate_button ${
activePag.current === i ? "current" : ""
} ${i > 0 ? "ml-1" : ""}`}
onClick={() => onClick(i)}
>
{number}
</Link>
))}
</span>
<Link
className="paginate_button next"
to="#"
onClick={() =>
activePag.current + 1 < paggination.length &&
onClick(activePag.current + 1)
}
>
Next
</Link>
</div>
</div>
</div>
</Table>
</div>
</div>
</div>
);
};
export default ActiveDevices;
And here is the code for a class component:
import React, { Component } from "react";
import { Dropdown } from "react-bootstrap";
import { Link } from "react-router-dom";
import DoctorsAccordion from "./DoctorsAccordion";
class Doctors extends Component {
componentDidMount(){
document.title = "Active Doctors"
}
render() {
return (
<React.Fragment>
<div className="form-head d-flex mb-3 mb-lg-5 align-items-start">
<Link onClick={this.onClick} className="btn btn-danger">
+ New Doctor
</Link>
<div className="input-group search-area ml-auto d-inline-flex">
<input type="text" className="form-control" placeholder="Search here" />
<div className="input-group-append">
<span className="input-group-text c-pointer">
<i className="flaticon-381-search-2"></i>
</span>
</div>
</div>
<Dropdown className="ml-3">
<Dropdown.Toggle variant="outline-primary" id="dropdown-basic">
<i className="flaticon-381-controls-3 "></i> Filter
</Dropdown.Toggle>
<Dropdown.Menu className="dropdown-menu-right">
<Dropdown.Item href="#">A To Z List</Dropdown.Item>
<Dropdown.Item href="#">Z To A List</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<Dropdown className="ml-3">
<Dropdown.Toggle variant="outline-primary" id="dropdown-basic">
Newest
</Dropdown.Toggle>
<Dropdown.Menu className="dropdown-menu-right">
<Dropdown.Item href="#">Newest</Dropdown.Item>
<Dropdown.Item href="#">Old</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<Link onClick={this.onClick} className="btn btn-outline-primary ml-3">
<i className="flaticon-381-menu-1 mr-0"></i>
</Link>
</div>
<DoctorsAccordion />
</React.Fragment>
);
}
}
export default Doctors;
Here is a screenshot showing functional compoenent path being updated in address bar but no getting logged on console:
Screenshot of functional comp path not logged
why can't you use `
props.location.pathnameinsted of
window.location.pathname
to determine the current path and refer this link Read the current full URL with React?

Ant Design modal appears few times in react js

Ant modal appears few times, but if i remove map function inside the modal then its works fine its appears only one time.
what may be the issue? please help me to solve this issue (Modal triggering/appears few times)
Ant modal code follows:
const [visibleVoucherModal, setVisibleVoucherModal] = useState(false);
const showVoucherModal = () => {
setVisibleVoucherModal(true)
}
const closeVoucherModal = () => {
setVisibleVoucherModal(false);
};
const SavedVoucherModal = () => {
return (
<Modal title="Select Any Voucher" visible={visibleVoucherModal} onCancel={closeVoucherModal} footer={null} >
{savedVoucherList.length >= 1 ?
<div>
<Checkbox.Group className="w-100" onChange={checkBox} value={voucherVal} >
{savedVoucherList.map((item, i) => {
return (
<div key={i}>
<Checkbox value={item.Id} className="w-100" onChange={e => { handleCheckBox(e, i) }}
checked={checked[i] || true} disabled={!checked[i] && disabled} >
<div className="pl-4">
<List.Item style={{ marginTop: "-35px" }} className="py-0">
<List.Item.Meta
// avatar={<img src={item.Photo == '' ? 'd' : item.Photo} alt="" width="72" />}
title={<span style={{ fontSize: "12px" }}>{item.Name}</span>}
description={<div className="small">Expiry Date: <br />{item.ExpireDate.slice(0, 10)}</div>}
/>
<div className="pt-1">
<p className="font-weight-bold text-primary mb-0">{numberFormat(item.Price)}</p>
<small><del>{numberFormat(item.OldPrice)}</del></small>
</div>
</List.Item>
</div>
</Checkbox>
<Divider className="m-0 p-0 mb-4" />
</div>)
})}
</Checkbox.Group>
</div> :
<p className="mb-4">Oops, there is no voucher applicable to this order</p>
}
<Button type="primary" className="font-weight-bold btn-round" onClick={closeVoucherModal}>Close</Button>
</Modal>
)
}
Button:
<Button type="default" className="text-primary border-right-0 border-left-0" size="large" onClick={showVoucherModal}>Redeem Voucher</Button>

Table Body in Semantic UI React with No Table Rows Causing validateDomNesting Error

I've gone through all of the example questions on this and can't seem to figure out what my problem is.
Here is the full error:
index.js:1375 Warning: validateDOMNesting(...): Text nodes cannot appear as a child of <tbody>.
in tbody (created by TableBody)
in TableBody (at Favorites.js:167)
in table (created by Table)
in Table (at Favorites.js:123)
in Favorites (created by ConnectFunction)
in ConnectFunction (at App.js:73)
in Route (at App.js:69)
in Router (created by BrowserRouter)
in BrowserRouter (at App.js:46)
in div (created by Container)
in Container (at App.js:44)
in App (created by ConnectFunction)
in ConnectFunction (at src/index.js:10)
in Provider (at src/index.js:9)
and my full code
import React, { useState, useEffect } from "react";
import Search from "./Search";
import { connect } from "react-redux";
import {
Table,
Popup,
Responsive,
Button,
Segment,
Header,
Image
} from "semantic-ui-react";
import { searchChange } from "../reducers/searchReducer";
import { fetchData } from "../reducers/baseballReducer";
import { removeFavorite } from "../reducers/favoriteReducer";
import { getFavorites } from "../reducers/favoriteReducer";
import { getUpdates } from "../reducers/updateReducer";
import { setNotification } from "../reducers/notificationReducer";
import _ from "lodash";
var moment = require("moment");
moment().format();
//Filter 'favupdates' state for user's input
const searchCards = ({ favUpdates, search }) => {
return search
? favUpdates.filter(a =>
a.title
.toString()
.toLowerCase()
.includes(search.toLowerCase())
)
: favUpdates;
};
const style = {
borderRadius: 0,
padding: "2em"
};
const Favorites = props => {
useEffect(() => {
document.title = "My Favorites | All Vintage Search";
}, []);
useEffect(() => {
props.getFavorites(props.loggedUser.id);
}, [props.loggedUser]);
//Set 'filteredData' state
useEffect(() => {
setData(props.cardsToShow);
}, [props]);
const mapFAVS = props.favorites;
const data = Array.from(mapFAVS);
const updatedFavs = data.map(item => item.id);
const formatFavs = updatedFavs.map(id => id.join(","));
console.log("FORMAT FAVS", formatFavs);
//Get updated data from eBay based on user's favorite id's and update 'favUpdates' state
useEffect(() => {
props.getUpdates(formatFavs);
}, [props.favorites]);
const [column, setColumn] = useState(null);
const [direction, setDirection] = useState(null);
const [filteredData, setData] = useState(props.cardsToShow);
console.log("Filtered Data", filteredData);
const handleSortNumeric = clickedColumn => {
const sorter = data => parseInt(data[clickedColumn]);
setData(_.sortBy(filteredData, sorter));
};
const handleSortReverse = () => {
const sorter = data => parseInt(data);
setData(_.sortBy(filteredData, sorter).reverse());
};
const handleSort = clickedColumn => {
if (column !== clickedColumn) {
setColumn(clickedColumn);
if (clickedColumn === "title" || "acceptsOffers" || "timeStamp") {
setData(_.sortBy(filteredData, [clickedColumn]));
} else {
handleSortNumeric(clickedColumn);
}
setDirection("ascending");
return;
}
if (clickedColumn === "title") {
setData(_.sortBy(filteredData.reverse()));
} else {
handleSortReverse();
}
direction === "ascending"
? setDirection("descending")
: setDirection("ascending");
};
const removeFavorite = card => {
props.removeFavorite(card, props.loggedUser);
props.setNotification(`You removed ${card.title}!`, 5);
};
if (!props.cardsToShow) return null;
return (
<>
<Search />
<Segment inverted color="blue">
<Header inverted color="grey" size="medium">
My Favorites
</Header>
</Segment>
<Segment>Count: {props.cardsToShow.length}</Segment>
<Responsive maxWidth={767}>
<strong>Click to Sort:</strong>
</Responsive>
<Table sortable celled fixed striped>
<Table.Header>
<Table.Row>
<Table.HeaderCell
textAlign="center"
sorted={column === "title" ? direction : null}
onClick={() => handleSort("title")}
>
Card Title
</Table.HeaderCell>
<Table.HeaderCell
width={2}
textAlign="center"
sorted={column === "updatedBids" ? direction : null}
onClick={() => handleSort("updatedBids")}
>
# Bids
</Table.HeaderCell>
<Table.HeaderCell
textAlign="center"
sorted={column === "updatedPrice" ? direction : null}
onClick={() => handleSort("updatedPrice")}
>
Price
</Table.HeaderCell>
<Table.HeaderCell
textAlign="center"
sorted={column === "timeStamp" ? direction : null}
onClick={() => handleSort("timeStamp")}
>
Time Left
</Table.HeaderCell>
<Table.HeaderCell
textAlign="center"
sorted={column === "status" ? direction : null}
onClick={() => handleSort("status")}
>
Status
</Table.HeaderCell>
<Table.HeaderCell textAlign="center" width={2}>
Remove
</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{!filteredData
? "Sorry No Cards Found"
: filteredData.map(card => (
<>
<Responsive maxWidth={767}>
<div className="ui piled compact segment">
<div className="ui card">
<div className="blurring dimmable image">
<div className="ui inverted dimmer">
<div className="content">
<div className="center">
<div className="ui red button view">
VIEW
</div>
</div>
</div>
</div>
<Image
src={card.image}
href={card.itemURL}
centered
style={{ padding: "5px" }}
/>
</div>
<div className="content">
<div
id="rate"
className="ui star rating right floated"
data-rating="3"
></div>
<div className="header">
<a href={card.itemURL}>{card.title}</a>
</div>
<div
className="meta"
style={{ padding: "5px 0 0 0" }}
>
<span className="date">
<i className="clock icon"></i> Ends in{" "}
{moment
.duration(card.timeLeft, "minutes")
.humanize()}
</span>
<div style={{ padding: "10px 0 0 0" }}>
<span>
<Button color="green">
${card.updatedPrice}
</Button>
</span>
<span class="right floated date">
{" "}
<Button
onClick={() => removeFavorite(card)}
color="red"
icon="remove circle"
/>
</span>
</div>
</div>
</div>
<div className="extra content">
<div
className="ui right labeled button"
data-content="Bids"
data-variation="tiny"
tabindex="0"
>
<div className="ui blue icon tiny button">
<i className="gavel large icon"></i>
</div>
<a
href={card.itemURL}
className="ui basic blue left pointing label"
>
{card.updatedBids}
</a>
</div>
<div
className="ui left labeled right floated button"
data-content="Watch Count"
data-variation="tiny"
tabindex="0"
>
<a
href={card.itemURL}
className="ui basic blue right pointing label"
>
{card.status}
</a>
<div className="ui blue icon tiny button">
<i className="history large icon"></i>
</div>
</div>
</div>
</div>
</div>
</Responsive>
<Responsive
as={"tr"}
minWidth={768}
style={{ width: "100%" }}
>
<Popup
trigger={
<Table.Cell>
<a href={card.itemURL} target={"_blank"}>
{card.title}
</a>
</Table.Cell>
}
content={
<img
alt={card.title}
src={card.image}
height="250"
></img>
}
style={style}
size="small"
position="left center"
></Popup>
<Table.Cell textAlign="center">
{card.updatedBids}
</Table.Cell>
<Table.Cell textAlign="center">
${card.updatedPrice}
</Table.Cell>
<Table.Cell textAlign="center">
{moment.duration(card.timeLeft, "minutes").humanize()}
</Table.Cell>
<Table.Cell textAlign="center">{card.status}</Table.Cell>
<Table.Cell textAlign="center">
<Button
onClick={() => removeFavorite(card)}
color="red"
icon="remove circle"
/>
</Table.Cell>
</Responsive>
</>
))}
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.HeaderCell colSpan="6"></Table.HeaderCell>
</Table.Row>
</Table.Footer>
</Table>
</>
);
};
const mapStateToProps = state => {
return {
baseball: state.baseball,
favorites: state.favorites,
favUpdates: state.favUpdates,
loggedUser: state.loggedUser,
page: state.page,
entries: state.entries,
query: state.query,
pageOutput: state.pageOutput,
search: state.search,
cardsToShow: searchCards(state)
};
};
const mapDispatchToProps = {
searchChange,
fetchData,
removeFavorite,
getFavorites,
getUpdates,
setNotification
};
export default connect(mapStateToProps, mapDispatchToProps)(Favorites);
I suspected the issue might be where i'm using the section as I dont have any table rows or cells set within the Table Body. I tried wrapping that whole section with a Table.Row and a Table.Cell, but still getting the same error. Any ideas?
If !filteredData === false then the only child of <Table.Body> is text.
As the error says, the table body cannot have text as a child.
Wrap the text like this <Table.Row><Table.Cell>Sorry no cards shown</Table.Cell></Table.Row>

Categories