How can we get value of selected menu item in Ant Design? - reactjs

Sandbox Link
I want to display the name of the selected item on the button.
Currently, the button says Select User Name but when someone selects a name, that name should be displayed instead.

Try this , it works for me
const App = () => {
const [itemName, setItemName] = useState("Select User Name");
const items = [
{ key: "1", label: "John" },
{ key: "2", label: "Peepo" },
{ key: "3", label: "Patel" },
{ key: "4", label: "Soukup" }
];
const menu = (
<Menu
items={items}
onClick={({ key }) => {
setItemName(items.find((elm) => elm.key === key).label);
}}
/>
);

You can use this approach of displaying the name on the button. On making an item as an object and passing it to the items params.
import React, { useState } from "react";
import "antd/dist/antd.css";
import "./index.css";
import { Menu, Dropdown, Button, Space } from "antd";
const App = () => {
const [itemName, setItemName] = useState("Select User Name");
const items = [
{ key: "1", label: "John" },
{ key: "2", label: "Peepo" },
{ key: "3", label: "Patel" },
{ key: "4", label: "Soukup" }
];
const menu = (
<Menu
items={items}
selectable
onSelect={({ key }) => {
setItemName(items[key - 1].label)
}}
/>
);
return (
<>
<h3>Selected user name should appear on the button</h3>
<Dropdown overlay={menu}>
<Button type="primary">
<Space>{itemName}</Space>
</Button>
</Dropdown>
</>
);
};
export default App;

Related

React - Encountered two children with the same key

I'm fairly new to React. I am working on a note app and when I add 2 notes, they have the same key and the next 2 notes also share their own key and so on. I started off with prop drilling from the App to the AddNote file via NotesList.js and it was working fine and the problem has only occurred since I used useContext API so maybe I am not coding the useContext in the correct way. The useContext component looks like this:
import { createContext } from "react";
const HandleAddContext = createContext();
export default HandleAddContext;
This is my App.js
import { useState } from "react";
import { v4 as uuid } from "uuid";
import NotesList from "./components/NotesList";
import HandleAddContext from "./components/UseContext/HandleAddContext";
const unique_id = uuid();
const small_id = unique_id.slice(0, 8);
const initialState = [
{
id: small_id,
text: "1st note",
date: "12/10/22022",
},
{
id: small_id,
text: "2nd note",
date: "15/10/22022",
},
{
id: small_id,
text: "3rd note",
date: "16/10/22022",
},
{
id: small_id,
text: "4th note",
date: "30/10/22022",
},
];
export const App = () => {
const [notes, setNote] = useState(initialState);
const addHandleNote = (text) => {
console.log(text);
const date = new Date();
const newNote = {
id: small_id,
text: text,
date: date.toLocaleDateString(),
};
console.log(newNote);
const newNotes = [...notes, newNote];
setNote(newNotes);
};
return (
<HandleAddContext.Provider value={addHandleNote}>
<div className="container">
<NotesList notes={notes} />
</div>
</HandleAddContext.Provider>
);
};
export default App;
This is the component with map notes
import Note from "./Note";
import AddNote from "./AddNote";
const NotesList = ({ notes }) => {
return (
<div className="notes-list">
{notes.map((note) => (
<Note key={note.id} id={note.id} text={note.text} date={note.date} />
))}
<AddNote />
</div>
);
};
export default NotesList;
This is the Note:
import { RiDeleteBin6Line } from "react-icons/ri";
const Note = ({ text, date }) => {
return (
<div className="note">
{/* <div> */}
<p>{text}</p>
{/* </div> */}
<div className="note-footer">
<p className="note-footer-text">{date}</p>
<RiDeleteBin6Line />
</div>
</div>
);
};
export default Note;
This is the AddNote.js component
import { useState } from "react";
import { RiSave2Line } from "react-icons/ri";
const AddNote = ({ handleAddNote }) => {
const [addText, setAddText] = useState("");
const [errorMsg, setErrorMsg] = useState("");
//handle text input
const handleChange = (e) => {
console.log(e.target.value);
setAddText(e.target.value);
};
//handle save
const handleSaveClick = () => {
if (addText.trim().length > 0) {
handleAddNote(addText);
}
};
return (
<div>
<textarea
rows="8"
cols="10"
placeholder="Type here to add a note..."
value={addText}
onChange={handleChange}
/>
<div>
<p>200 characters remaining</p>
<RiSave2Line onClick={handleSaveClick} />
</div>
</div>
);
};
export default AddNote;
The issue is your unique_id and small_id are only being generated once due to your function call syntax.
const unique_id = uuid();
Assigns unique_id the result of uuid(), rather than referencing the function. And therefore small_id is simply slicing the already generated uuid. To fix this your must generate a new uuid every time you create a note. Your can create a function that return a new 'small ID' everytime.
function genSmallID() {
return uuid().slice(0, 8);
}
And now when you create your initial notes use the function:
const initialState = [{
id: genSmallID(),
text: "1st note",
date: "12/10/22022",
}, {
id: genSmallID(),
text: "2nd note",
date: "15/10/22022",
}, {
id: genSmallID(),
text: "3rd note",
date: "16/10/22022",
}, {
id: genSmallID(),
text: "4th note",
date: "30/10/22022",
}];
by setting a variable
const small_id = unique_id.slice(0, 8);
you create a variable and assign it to each element of your initialState array's id.
you should delete small_id and unique_id and do this:
const initialState = [{
id: uuid().slice(0, 8),
text: "1st note",
date: "12/10/22022",
}, {
id: uuid().slice(0, 8),
text: "2nd note",
date: "15/10/22022",
}, {
id: uuid().slice(0, 8),
text: "3rd note",
date: "16/10/22022",
}, {
id: uuid().slice(0, 8),
text: "4th note",
date: "30/10/22022",
}];
In order to have different id (here you have always the same), or if the id isn't relevant for you you can always use the element's position in the array as key with the 2nd parameter of the map function like this:
<div className="notes-list">
{notes.map((note, key) => (
<Note key={key} id={note.id} text={note.text} date={note.date} />
))}
<AddNote />

Shopify Polaris: handleSelectionChange's SelectionType.Single is not working in IndexTable

I want to make IndexTable's checkbox a single selection. And I implemented it like the one below, but the checking is not working properly. I mean I can select one element, but I can't change the selection when I click another element. Also, the upper item's counter is keeping incrementing. I just want to set one id in selectedResources.
Here is sandbox. https://codesandbox.io/s/keen-cloud-j2onnj?file=/App.js:715-732
import React, { useState } from "react";
import {
IndexTable,
TextStyle,
Card,
useIndexResourceState,
IndexTableSelectionType
} from "#shopify/polaris";
function SimpleSmallScreenIndexTableExample() {
const [selectedId, setSelectedId] = useState("");
const customers = [
{
id: "3412",
url: "customers/341",
name: "Mae Jemison",
location: "Decatur, USA",
orders: 20,
amountSpent: "$2,400"
},
{
id: "2562",
url: "customers/256",
name: "Ellen Ochoa",
location: "Los Angeles, USA",
orders: 30,
amountSpent: "$140"
}
];
const resourceName = {
singular: "customer",
plural: "customers"
};
const {
selectedResources,
allResourcesSelected,
handleSelectionChange
} = useIndexResourceState(customers);
console.log(selectedResources);
const rowMarkup = customers.map(
({ id, name, location, orders, amountSpent }, index) => (
<IndexTable.Row
id={id}
key={id}
selected={selectedResources.includes(id)}
position={index}
onClick={() => setSelectedId(id)}
>
<div style={{ padding: "12px 16px" }}>
<p>
<TextStyle variation="strong">{name}</TextStyle>
</p>
<p>{location}</p>
<p>{orders}</p>
<p>{amountSpent}</p>
</div>
</IndexTable.Row>
)
);
return (
<div style={{ width: "430px" }}>
<Card>
<IndexTable
resourceName={resourceName}
itemCount={customers.length}
selectedItemsCount={
allResourcesSelected ? "All" : selectedResources.length
}
onSelectionChange={() =>
handleSelectionChange(
IndexTableSelectionType.Single,
true,
selectedId
)
}
condensed
headings={[
{ title: "Name" },
{ title: "Location" },
{ title: "Order count" },
{ title: "Amount spent" }
]}
>
{rowMarkup}
</IndexTable>
</Card>
</div>
);
}
export default SimpleSmallScreenIndexTableExample;

Select dependendent on each others reactjs

On selecting first dropdown then the second dropdown should show corresponding phonenumber in second dropdownlist and vice versa .how can we achieve it?
Code
import Select from "react-select";
const data = [
{ value: 1, label: "max", phone: "123" },
{ value: 2, label: "sam", phone: "345" },
{ value: 3, label: "denis", phone: "4444" }
];
export default function App(props) {
const [select1, setSelect1] = useState([]);
const [select2, setSelect2] = useState([]);
const filter1=data.filter((x)=>{return x.value===select2.value})
const filter2=data.filter((x)=>{return x.value===select1.value})
return (
<div className="App">
<Select
options={data}
value={select1}
onChange={(e) => {
console.log(e);
setSelect1(e);
setSelect2(e.phone);
}}
/>
<Select
options={data}
value={select2}
onChange={(e) => {
setSelect2(e);
setSelect1(e.value);
}}
/>
</div>
);
}

react material-ui mui-datatables onRowSelectionChange ID

This is my react code. I am using the material UI. I am working with ID related events. the full code is provided below.
Here, the index ID is getting automatically generated. The issue has to do with that.
import React, { useState } from "react";
import ReactDOM from "react-dom";
import MUIDataTable from "mui-datatables";
import InputLabel from "#material-ui/core/InputLabel";
import MenuItem from "#material-ui/core/MenuItem";
import FormHelperText from "#material-ui/core/FormHelperText";
import FormControl from "#material-ui/core/FormControl";
import Select from "#material-ui/core/Select";
function Ag() {
const [responsive, setResponsive] = useState("vertical");
const onCellClick = () => {
console.log("sadf");
};
const onRowsDelete = () => {
console.log("remove");
};
const onRowSelectionChange = (ev, ex, ez) => {
console.log(ez);
};
const columns = ["Name", "Title", "Location"];
const options = {
filter: true,
filterType: "dropdown",
responsive,
onCellClick,
onRowsDelete,
onRowSelectionChange,
};
const data = [
{
Id: "1",
Name: "sunder",
Title: "dlamds",
Location: "asdfsa",
},
{
Id: "2",
Name: "cvzx",
Title: "sadfsda",
Location: "sadfsdacv",
},
{
Id: "3",
Name: "dsfas",
Title: "werq",
Location: "ewqrwqe",
},
{
Id: "4",
Name: "wqer",
Title: "gfdsg",
Location: "bvcxb",
},
{
Id: "5",
Name: "ereq",
Title: "qwer",
Location: "sdafas",
},
];
return (
<React.Fragment>
<MUIDataTable
title={"ACME Employee list"}
data={data}
columns={columns}
options={options}
/>
</React.Fragment>
);
}
export default Ag;
I want to get a data ID instead of an index ID that was automatically generated when I clicked.
What should I do?
onRowSelectionChange: (currentSelect, allSelected) => {
const result = allSelected.map(item => { return data.at(item.index) });
const selectedIds = result.map(item => {
return item.id;
});
console.log(selectedIds);
}

how to give navigation for list in horizontal menu of reactjs

Can any one help to get the solution for this question, for page navigation i am using react-horizontal-scrolling-menu. in the reactjs application. Just i want give page navigation where i should give navigation please tell me. this code has giving by the link https://https://www.npmjs.com/package/react-horizontal-scrolling-menu
import React, { Component } from 'react';
import ScrollMenu from 'react-horizontal-scrolling-menu';
import './App.css';
// list of items
const list = [
{ name: 'item1' },
{ name: 'item2' },
{ name: 'item3' },
{ name: 'item4' },
{ name: 'item5' },
{ name: 'item6' },
{ name: 'item7' },
{ name: 'item8' },
{ name: 'item9' }
];
// One item component
// selected prop will be passed
const MenuItem = ({text, selected}) => {
return <div
className={`menu-item ${selected ? 'active' : ''}`}
>{text}</div>;
};
// All items component
// Important! add unique key
export const Menu = (list, selected) =>
list.map(el => {
const {name} = el;
return <MenuItem text={name} key={name} selected={selected} />;
});
const Arrow = ({ text, className }) => {
return (
<div
className={className}
>{text}</div>
);
};
const ArrowLeft = Arrow({ text: '<', className: 'arrow-prev' });
const ArrowRight = Arrow({ text: '>', className: 'arrow-next' });
const selected = 'item1';
class App extends Component {
constructor(props) {
super(props);
// call it again if items count changes
this.menuItems = Menu(list, selected);
}
state = {
selected
};
onSelect = key => {
this.setState({ selected: key });
}
render() {
const { selected } = this.state;
// Create menu from items
const menu = this.menuItems;
return (
<div className="App">
<ScrollMenu
data={menu}
arrowLeft={ArrowLeft}
arrowRight={ArrowRight}
selected={selected}
onSelect={this.onSelect}
/>
</div>
);
}
}
'css code start here '
.menu-item {
padding: 0 40px;
margin: 5px 10px;
user-select: none;
cursor: pointer;
border: none;
}
.menu-item-wrapper.active {
border: 1px blue solid;
}
.menu-item.active {
border: 1px green solid;
}
.scroll-menu-arrow {
padding: 20px;
cursor: pointer;
}
You are missing specified paths (or what resolves to pathnames) from your list of routes that are passed to the Link component's to prop.
// list of items
const list = [
{ name: "item1", path: "/" },
{ name: "item2" }, // MISSING path properties!
{ name: "item3", path: "./abcd" },
{ name: "item4" },
{ name: "item5" },
{ name: "item6" },
{ name: "item7" },
{ name: "item8" },
{ name: "item9", path: "./example_1" }
];
// One item component
// selected prop will be passed
const MenuItem = ({ text, path, selected }) => {
return (
<div className={`menu-item ${selected ? "active" : ""}`}>
<NavLink exact to={path}> // All links must have a defined to prop
{text}
</NavLink>
</div>
);
};
It is a simple fix to add a defined path for each route in your config. For example:
const list = [
{ name: "item1", path: "/" },
{ name: "item2", path: "/page/1" },
{ name: "item3", path: "/abcd" },
{ name: "item4", path: "/page/2" },
{ name: "item5", path: "/page/3" },
{ name: "item6", path: "/page/4" },
{ name: "item7", path: "/page/42" },
{ name: "item8", path: "/example_1" },
{ name: "item9", path: "/page/5" }
];
DEMO I've taken the liberty of forking your sandbox, updated to specify paths, and only define the menu once and display in one location (DRY principle) in your root App.
Link to this library is not working.
You can add another property to your list like { name: 'item1', url: '/somecomponenturl' }
Then in your Menu function just pass the URL as prop just like text prop and in MenuItem function use your url with Link or NavLink like:
const MenuItem = ({text, url, selected}) => {
return <div
className={`menu-item ${selected ? 'active' : ''}`}
><Link to={url}>{text}</Link></div>;
};
export const Menu = (list, selected) =>
list.map(el => {
const {name} = el;
const {url} = el;
return <MenuItem text={name} url={url} key={name} selected={selected} />;
});

Resources