i want get all the data from dataFromes and put it in Modal.title but what i did using map it only show the first in array of dataFromes
import React, { useState } from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
import Form from 'react-bootstrap/Form';
import { useSelector } from 'react-redux';
function ViewPop(props) {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const dataFromes = useSelector(state => state.data.value);
const expenseForms = useSelector(state => state.expend.value);
return (
<div>
<Button variant= {props.outline} onClick={() => {
handleShow();
}} className= "mx-1">
{props.text}
</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<div className='title flex'>
{dataFromes.map((data, index) => (
<Modal.Title>Expenses - {data.text}</Modal.Title>
))}
<Button variant="outline-danger" className='ml-2'>Delete</Button>
</div>
</Modal.Header>
<Form className="mx-3 mt-3">
<Form.Group className="mb-3">
{expenseForms ? expenseForms.map(expense => (
<div key={expense.text} className='expense flex justify-between items-center mb-3'>
<span className='fs-4'>{expense.text}</span>
<span className='fs-5'><span>$</span>{expense.amount} <Button className= "text-center mb-[9px] w-7 ml-1" size="sm" variant="outline-danger"><span className="text-[10px]">X</span></Button></span>
</div>
)) : null}
</Form.Group>
</Form>
{/* <Modal.Title>Expenses - {data.text}</Modal.Title> */}
</Modal>
</div>
)
};
export default ViewPop;
hello i want get all the data from dataFromes and put it in Modal.title but what i did using map it only show the first in array of dataFromes
React-hook-form issue:
I have a table which is responsive, but the layout is different so I have 2 different component for this.
This is a table, where the user can edit it's content.
Here is the layout:
When the user clicks on the green button, the editing will be done, and the values will be saved. It's a bit tricky, because the the button trigger the react-hook-form onSubmit which is in a different component solved with forwardRef.
("react-hook-form": "^7.38.0",)
Here is the EditableView code:
import React, { forwardRef } from "react";
import { useForm, useFieldArray } from "react-hook-form";
import { useProfileContext } from "../../context/ProfileContext";
import PrimaryButton from "../Button/PrimaryButton";
const EditableDayMenu = forwardRef(({ weekOfYear, dayOfWeek, menu }, ref) => {
const { register, control, handleSubmit, watch, getValues } = useForm({
defaultValues: {
menu: menu?.map((item) => {
return {
menuCategory: item.menuCategory,
menuDescription: item.menuDescription,
};
}),
},
});
const { fields, append, remove } = useFieldArray({
control,
name: "menu",
});
const { handleMenu } = useProfileContext();
const onSubmit = (data) => {
console.log(Data);
handleMenu(weekOfYear, dayOfWeek, data);
};
console.log(watch());
return (
<form onSubmit={handleSubmit(onSubmit)}>
{fields.map((item, index) => {
return (
<div className="" key={item.id}>
<label className="block text-gray-700 text-sm font-bold mb-2">
Menü kategória
</label>
<input
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
{...register(`menu.${index}.menuCategory`, { required: true })}
/>
<label className="block text-gray-700 text-sm font-bold mb-2">
Menü leírása
</label>
<textarea
rows={5}
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
{...register(`menu.${index}.menuDescription`, { required: true })}
/>
<button
className="mb-3"
type="button"
onClick={() => remove(index)}
>
Menü törlése
</button>
</div>
);
})}
<button
className="block lg:hidden xl:block mx-auto"
type="button"
onClick={() => {
append({ menuCategory: "", menuDescription: "" });
}}
>
<PrimaryButton text={"Új menü hozzáadása"} />
</button>
<button
className="hidden lg:block xl:hidden mx-auto"
type="button"
onClick={() => {
append({ menuCategory: "", menuDescription: "" });
}}
>
<PrimaryButton text={"+"} />
</button>
<button hidden={true} ref={ref} type={"submit"} />
</form>
);
});
export default EditableDayMenu;
EditableDayMenu.displayName = "EditableDayMenu";
The whole menu with the refs:
const WeeklyMenu = ({ allMenu, isEditable = true }) => {
const [currentWeek, setCurrentWeek] = useState();
const [isEditView, setIsEditView] = useState(false);
const fixWeek = Number(moment().format("w"));
const arrLength = 7;
const elRefs = React.useRef([]);
const mobileelRefs = React.useRef([]);
const [isMobileView, setIsMobileView] = useState();
const handleResize = () => {
window.innerWidth>1024 ? setIsMobileView(false) :
setIsMobileView(true)
}
if (elRefs.current.length !== arrLength) {
// add or remove refs
elRefs.current = Array(arrLength)
.fill()
.map((_, i) => elRefs.current?.[i] || createRef());
}
if (mobileelRefs.current.length !== arrLength) {
// add or remove refs
mobileelRefs.current = Array(arrLength)
.fill()
.map((_, i) => mobileelRefs.current?.[i] || createRef());
}
const menuThisWeek = menuOfTheWeek(currentWeek);
return (
<div className="text-Brand-Primary relative pt-4 lg:pt-0">
{menuThisWeek != null && isEditable && (
<div className="flex items-center gap-x-2 absolute right-0 w-full justify-center sm:w-fit">
{!isEditView ? (
<button
onClick={() => setIsEditView(true)}
className="bg-Brand-Secondary rounded-2xl px-3 py-2 text-white hover:bg-opacity-80"
>
Menü szerkesztése
</button>
) : (
<button
onClick={() => {
setIsEditView(false);
const weekResponsiveButtons = isMobileView ? mobileelRefs : elRefs
console.log(isMobileView)
weekResponsiveButtons.current.forEach((ref) => {
console.log(ref.current);
ref.current?.click();
});
}}
className="bg-green-500 rounded-2xl px-3 py-2 text-white hover:bg-opacity-80"
>
Mentés
</button>
)}
</div>
)}
<div className="block lg:hidden h-12" />
<p className="text-3xl">Heti menü</p>
<div className="w-full space-x-3 hidden lg:flex">
<DesktopWeeklyMenu
isEditView={isEditView}
weeks={getCurrentWeek(fixWeek - currentWeek)}
menus={menuThisWeek}
currentWeek={currentWeek}
elRefs={elRefs}
menuThisWeek={menuThisWeek}
/>
</div>
{(
<MobileWeeklyMenu
isEditView={isEditView}
weeks={getCurrentWeek(fixWeek - currentWeek)}
menus={menuThisWeek}
currentWeek={currentWeek}
elRefs={mobileelRefs}
menuThisWeek={menuThisWeek}
/>
)}
{menuThisWeek == null && (
<UnlockMenuWeek weekOfYear={currentWeek} isEditable={isEditable} />
)}
</div>
);
};
export default WeeklyMenu;
When I try to edit in the desktop layout, it works perfectly, in the mobile layout it's not, although we are using the same EditableDayMenu component in both:
const onSubmit = (data) => {
handleMenu(weekOfYear, dayOfWeek, data)
};
console.log(watch())
When we try to submit the form, the data only shows the old (defaultValues), but the console.log(watch()) prints out the latest updated fields, so I don't understand why it is not the same in the onsubmit (and what is the difference between my desktop and mobile approach?)
Desktop layout:
import React from 'react'
import EditableDayMenu from './EditableDayMenu';
const DesktopWeeklyMenu = ({
isEditView,
weeks,
menus,
currentWeek,
elRefs,
menuThisWeek,
}) => {
return (
<table className="table-fixed w-[90%] mx-auto border-2 border-gray-500 rounded-xl">
<thead>
<tr>
{weeks.map((item) => {
return (
<th
key={item}
className="border border-gray-400 text-Brand-Secondary px-1 xl:px-6"
>
{item}
</th>
);
})}
</tr>
</thead>
<tbody>
<tr>
{menuThisWeek?.map((day, dayOfWeek) => {
return (
<td
key={day + dayOfWeek}
valign="top"
className="border border-gray-400 p-1 2xl:p-3"
>
<div className="flex flex-col gap-y-3">
{!isEditView &&
day.day?.map((menu, idx) => {
return (
<div key={menu.menuCategory + idx}>
<p className="font-bold text-lg">
{menu.menuCategory}
</p>
<p className="font-base text-gray-700 break-all">
{menu.menuDescription}
</p>
</div>
);
})}
</div>
{isEditView && (
<EditableDayMenu
ref={elRefs.current[dayOfWeek]}
weekOfYear={currentWeek}
dayOfWeek={dayOfWeek}
menu={day.day}
/>
)}
</td>
);
})}
</tr>
</tbody>
</table>
)
}
export default DesktopWeeklyMenu
Mobile layout:
import React from "react";
import EditableDayMenu from "./EditableDayMenu";
import UnlockMenuWeek from "./UnlockMenuWeek";
const MobileWeeklyMenu = ({
isEditView,
weeks,
menus,
currentWeek,
elRefs,
menuThisWeek,
}) => {
return (
<table className="w-full mx-auto border-collapse border-spacing-10 block lg:hidden whitespace-normal border-2 border-gray-500 rounded-xl overflow-x-auto">
{weeks.map((week, dayOfWeek) => {
return (
<tr key={week}>
<th className="border w-[30%] border-gray-400 text-Brand-Secondary px-1 xl:px-6">
{week}
</th>
<td valign="top" className={`border border-gray-400 p-3 ${menuThisWeek==null ? 'bg-slate-200' :''}`}>
{menus?.[dayOfWeek]?.day?.map((day, index) => {
return !isEditView ? (
<div key={day.menuCategory + index}>
<p className="font-bold text-lg">{day.menuCategory}</p>
<p className="font-base text-gray-700 break-all">
{day.menuDescription}
</p>
</div>
) : (
<EditableDayMenu
key={day.menuCategory + index+"edit"}
ref={elRefs.current[dayOfWeek]}
weekOfYear={currentWeek}
dayOfWeek={dayOfWeek}
menu={menus?.[dayOfWeek]?.day}
/>
);
})}
</td>
</tr>
);
})}
</table>
);
};
export default MobileWeeklyMenu;
Here is an example of the log in the mobile layout:
Watch:
{menu: Array(3)}menu: Array(3)0: {menuCategory: 'EDIT CATEGORY NAME', menuDescription: 'Leves minden leírva blabla, második'}1: ...
OnSubmit:
{menu: Array(3)}menu: Array(3)0: {menuCategory: 'a1', menuDescription: 'Leves minden leírva blabla, második'}1: ...
After save:
You can see, that the edited value will not be stored, it's very strange, because the same works in the desktop version, hope you guys can help me figure it out.
I'm trying to use React to make a Dungeons and Dragons Character Sheet (click here for a preview). One component I am stuck on is the ability modifier, shown below:
With React.useState(), I can automatically changes the number "7" by clicking the arrows
I've cracked the basics of useState(). I can now change the variable titled count in the red circle if I click the MUI arrow buttons. I want the string value (now set to "15") to be dynamic, and equal to (count-10)/2.
I am trying to use onChange to make it work, but no luck. My code for the component is shown below. What am I doing wrong?
`
import React from "react"
import ArrowBackIosIcon from '#mui/icons-material/ArrowBackIos';
import ArrowForwardIosIcon from '#mui/icons-material/ArrowForwardIos';
import Button from '#mui/material/Button';
export default function StatBox(props) {
const[count, setCount] = React.useState(8)
const incrementCount = () => {
setCount(count+1);
}
let modifier = "15"
if (count && !isNaN){
const modifierNum = Math.floor(Number(count)-10/2)
if(modifierNum > 0){
modifier = "+" + modifierNum
}
else{
modifier = modifierNum.toString()
}
}
const decrementCount = () => {
setCount(count-1);
}
return (
<div className="col text-center border border-danger rounded mt-2 mb-2">
<label>{props.stats}</label>
<div className="d-and-d-statbox-modifier">{modifier}</div>
<div className="row justify-content-center mb-2">
<Button
onClick={decrementCount}
onChange={(e) => count.onChange(count, e.target.value)}
size="sm"
variant="contained"
color="error"
>
<ArrowBackIosIcon fontSize="small" />
</Button>
<div>
<span className="mx-1 border-danger text-center dndstatrow">
{count}
</span>
</div>
<Button
onClick={incrementCount}
onChange={(e) => count.onChange(count, e.target.value)}
size="sm"
variant="contained"
color="error"
>
<ArrowForwardIosIcon fontSize="small" />
</Button>
</div>
</div>
);
}
`
Solved!
import React from "react"
import ArrowBackIosIcon from '#mui/icons-material/ArrowBackIos';
import ArrowForwardIosIcon from '#mui/icons-material/ArrowForwardIos';
import Button from '#mui/material/Button';
export default function StatBox(props) {
const[count, setCount] = React.useState(8)
const incrementCount = () => {
setCount(count+1);
}
let modifierNum = Math.floor(((count)-10)/2)
let modifier = ""
if(modifierNum > 0){
modifier = "+" + modifierNum
}
else{
modifier = modifierNum.toString()
}
const decrementCount = () => {
setCount(count-1);
}
return (
<div className="col text-center border border-danger rounded mt-2 mb-2">
<label>{props.stats}</label>
<div className="d-and-d-statbox-modifier">{modifier}</div>
<div className="row justify-content-center mb-2">
<Button
onClick={decrementCount}
size="sm"
variant="contained"
color="error"
>
<ArrowBackIosIcon fontSize="small" />
</Button>
<div>
<span className="mx-1 border-danger text-center dndstatrow">
{count}
</span>
</div>
<Button
onClick={incrementCount}
size="sm"
variant="contained"
color="error"
>
<ArrowForwardIosIcon fontSize="small" />
</Button>
</div>
</div>
);
}
I am still not familiar with react.js and I am doing a NFT app whereby you click a button and each individual NFT profile will show in a popup modal box which I have already successful integrate the modal box and able to pass the value to a function handleShow(owner) but I have no idea how to send or display this value (owner) into my modal box. Appreciate you guys, can help on my situation. thank you.
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
function handleShow(owner) {
alert(owner);
setShow(true);
}
<div className="min-h-screen bg-gray-100">
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8 ">
<div className="text-black-100 text-6xl pt-28 pb-10">Monkey</div>
{mintedNftState.state === "PENDING" && (
<div className="text-xl text-white">LOADING...</div>
)}
{mintedNftState.state === "SUCCESS" && (
<div className="grid grid-cols-3 gap-4">
{mintedNftState.data.map(
({ id, image, name, description, owner }) => {
return (
<div key={id} className="bg-white rounded p-2">
<img src={image} className="mx-auto p-4" alt={name} />
<div className="text-xl">{name}</div>
<div className="font-myfont">{description}</div>
<hr className="my-4" />
<div className="text-left text-sm">Owned By:</div>
<div className="text-left text-xs">{owner}</div>
<div className="mt-12">
<Button variant="primary" onClick={() => handleShow(owner)}>
Launch demo modal
</Button>
</div>
</div>
);
}
)}
</div>
)}
</div>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</div>
I would first add an owner state
const [owner, setOwner] = useState(null);
In handleShow you can set the owner like this
function handleShow(owner) {
setOwner(owner)
setShow(true);
}
You can finally display the owner value between <Modal.Body> tags
<Modal.Body>
<p>{owner}</p>
</Modal.Body>
When closing the modal you can set the owner to null
const handleClose = () => {
setShow(false);
setOwner(null);
}
import React, { Component } from "react";
import Header from "components/Headers/Header.jsx";
import Consumer from "../../context";
import {
Card,
CardHeader,
CardFooter,
DropdownMenu,
DropdownItem,
UncontrolledDropdown,
DropdownToggle,
Pagination,
PaginationItem,
PaginationLink,
Table,
Container,
Row
} from "reactstrap";
class Products extends Component {
render() {
return (
<>
<Header />
<Consumer>
{value => {
const { products } = value;
return (
<Container className="mt--7" fluid>
<Row>
<div className="col">
<Card className="shadow">
<CardHeader className="border-0">
<div className="d-flex justify-content-between">
<h3 className="mb-0">
<span className="text-info">Products</span>
</h3>
<a
href="/add/addproduct"
className="btn btn-outline-success"
>
<icon className="ni ni-fat-add "></icon>
</a>
</div>
</CardHeader>
<Table
className="align-items-center table-flush"
responsive
>
<thead className="thead-light">
<tr>
<th scope="col">
<span className="text-info">Prooduct Name</span>
</th>
<th scope="col">
<span className="text-info text-right">*</span>
</th>
<th scope="col" />
</tr>
</thead>
<tbody>
{products.map(product => {
return (
<tr>
<td>
<span className="mb-0 text-sm font-weight-bold">
{product.ProductName}
</span>
</td>
<td className="text-right">
<UncontrolledDropdown>
<DropdownToggle
className="btn-icon-only text-info"
href="#pablo"
role="button"
size="sm"
color=""
onClick={e => e.preventDefault()}
>
<i className="fas fa-ellipsis-v" />
</DropdownToggle>
<DropdownMenu
className="dropdown-menu-arrow"
right
>
<DropdownItem
href="#pablo"
onClick={e => e.preventDefault()}
>
Delete
</DropdownItem>
<DropdownItem
href="#pablo"
onClick={e => e.preventDefault()}
>
Update
</DropdownItem>
<DropdownItem
href="#pablo"
onClick={e => e.preventDefault()}
>
Go To Page
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</td>
</tr>
);
})}
</tbody>
</Table>
<CardFooter className="py-4">
<nav aria-label="...">
<Pagination
className="pagination justify-content-end mb-0"
listClassName="justify-content-end mb-0"
>
<PaginationItem className="disabled">
<PaginationLink
href="#pablo"
onClick={e => e.preventDefault()}
tabIndex="-1"
>
<i className="fas fa-angle-left" />
<span className="sr-only">Previous</span>
</PaginationLink>
</PaginationItem>
<PaginationItem className="active">
<PaginationLink
href="#pablo"
onClick={e => e.preventDefault()}
>
1
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink
href="#pablo"
onClick={e => e.preventDefault()}
>
2 <span className="sr-only">(current)</span>
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink
href="#pablo"
onClick={e => e.preventDefault()}
>
3
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink
href="#pablo"
onClick={e => e.preventDefault()}
>
<i className="fas fa-angle-right" />
<span className="sr-only">Next</span>
</PaginationLink>
</PaginationItem>
</Pagination>
</nav>
</CardFooter>
</Card>
</div>
</Row>
</Container>
);
}}
</Consumer>
</>
);
}
}
export default Products;
After adding a product in a React project, we redirect to the page where the products are listed, but the last product I added before refreshing the page does not appear in the list.
import React, { Component } from "react";
import Header from "components/Headers/Header.jsx";
import axios from "axios";
import Consumer from "../../context";
import { withRouter } from "react-router-dom";
class AddProduct extends Component {
state = {
ProductName: ""
};
validateForm = () => {
const { ProductName } = this.state;
if (ProductName === "") {
return false;
}
return true;
};
changeInput = e => {
this.setState({
[e.target.name]: e.target.value
});
};
addProduct = async (dispatch, e) => {
e.preventDefault();
const { ProductName } = this.state;
const newProduct = {
ProductName
};
if (!this.validateForm()) {
this.setState({
error: true
});
return;
}
const response = await axios.post(
"http://localhost:54663/api/product/addproduct",
newProduct
);
dispatch({ type: "ADD_Product", payload: response.data });
// Redirect
this.props.history.push("/admin/products", [ProductName]);
};
render() {
const { ProductName } = this.state;
return (
<>
<Header />
<Consumer>
{value => {
const { dispatch } = value;
return (
<div className="container mt-4">
<form onSubmit={this.addProduct.bind(this, dispatch)}>
<div className="form-group mt-4">
<label htmlFor="exampleInputEmail1">Product Name</label>
<input
type="text"
className="form-control"
name="ProductName"
id="productName"
placeholder="Product Name"
value={ProductName}
onChange={this.changeInput}
/>
</div>
<button type="submit" className="btn btn-primary">
Add
</button>
<a href="/admin/products" className="btn btn-warning">
Cancel
</a>
</form>
</div>
);
}}
</Consumer>
</>
);
}
}
export default withRouter(AddProduct);
And,
I want to see the data added to the products table using the API on the current page.
Even though it is redirecting now, I can't see the last data added before the page is refreshed.