adding specefic data from in array without loop - reactjs

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

Related

React: How to update a variable that depends on a state changes

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>
);
}

Set unique key for useState with multiple inputs

I have an App with 2 inputs where you can choose 1 muscle and a number of exercices for this muscle.
I added an "Add" button to duplicates these inputs to add a new muscle to work with its number of exercices.
The problem is, when I change an input, all same inputs will change because they have the same key (I guess).
Anyone can show me how to solve this ?
Here is my code :
import { Formik, Form, Field } from "formik";
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { getAllMuscles, numberOfExercices } from "../helpers/dataModuler";
import { setInLocalStorage } from "../helpers/localStorageHandler";
export const ProgramForm: React.FC<{}> = () => {
const [numberOfMusclesInProgram, setNumberOfMusclesInProgram] = useState(1);
const navigate = useNavigate();
const listOfMuscles = getAllMuscles();
const initialValues = {
numberOfExercices: 0,
muscle: listOfMuscles[0]
};
const handleSubmit = (values: {}) => {
setInLocalStorage("program", values);
navigate("/programme");
};
return (
<>
<Formik
initialValues={initialValues}
onSubmit={(values) => handleSubmit(values)}
>
<Form>
<div id="container">
{[...Array(numberOfMusclesInProgram)].map((n, i) => (
<DisplayMuscleInProgram key={n} />
))}
</div>
<button
onClick={() =>
setNumberOfMusclesInProgram(numberOfMusclesInProgram + 1)
}
type="button"
className="rounded-md border"
>
Add
</button>
<div className="text-center">
<button
type="submit"
className="mt-8 rounded-lg bg-primary p-2 text-white"
>
Let's gooooo 💪
</button>
</div>
</Form>
</Formik>
</>
);
};
export const DisplayMuscleInProgram = (props: { key: any }) => {
const listOfMuscles = getAllMuscles();
return (
<>
<div className="my-4 grid grid-cols-5 justify-between gap-5">
<Field
as="select"
className="col-span-3 rounded-lg bg-lightGray p-3"
name={`muscle-${props.key}`}
>
{listOfMuscles.map((muscle, key) => (
<option key={key}>{muscle}</option>
))}
</Field>
<Field
as="select"
className="col-span-2 rounded-lg bg-lightGray p-3"
name="numberOfExercices"
>
{numberOfExercices(10)}
</Field>
</div>
</>
);
};
In ProgramForm replace <div id="container" /> with the following (replacing key={n} with key={i}):
<div id="container">
{[...Array(numberOfMusclesInProgram)].map((n, i) => (
<DisplayMuscleInProgram key={i} />
))}
</div>
Alternatively, you may try:
<div id="container">
{[...Array(numberOfMusclesInProgram).keys()].map((n) => (
<DisplayMuscleInProgram key={n} />
))}
</div>
Source: https://stackoverflow.com/a/33352604/975164
Currently, all your inputs have exactly the same name because of the following lines in DisplayMuscleInProgram:
<Field
as="select"
className="col-span-3 rounded-lg bg-lightGray p-3"
name={`muscle-${props.key}`} // this line
>
React docs recommend using someEntity.id as keys and warn against using indexes as keys when the order of list items is expected to change. However, in this case, I believe you will be safe.
As a side note: Since you are using Formik, I recommend using Formik's built-in <FieldArray /> for this purpose i.e. add more inputs to the form on button click. You may read more about it here: https://formik.org/docs/api/fieldarray

Dynamic add Image and data with Ant-Design and ReactJs

I can't add an image while executing. When adding an image, the image does not appear, I use a dynamic form with the same inputs when adding a form which will later be stored by looping, but I have problems when adding images. I use a plugin from ant design.
Here's the code.
import React,{useState} from 'react'
import { Button,Form,Input } from 'antd';
import {
PlusOutlined,
MinusCircleOutlined,
} from '#ant-design/icons';
function Ad_abhb() {
const [Img1,setImg] = useState([]);
const i = 0;
const AddImg4 = (i) =>{
const [imgPrev1,setImgPrev1] = useState('');
const ImgC1=(e)=>{
const reader = new FileReader();
const vImg = e.target.files[0];
setImgPrev1(URL.createObjectURL(vImg));
reader.readAsDataURL(vImg);
reader.onload = () => {[...setImg(reader.result)]}
}
return(<>
<Form.Item className='imgHobi'>
<Input id={'uImg4'+i.kd} type="file" accept=".jpg,.jpeg,.png" onChange={ImgC1} hidden />
<label htmlFor={'uImg4'+i.kd}>
{imgPrev1.length >= 1 ?<>
<div className='imgLoad'>
<img src={imgPrev1} className='getImg' alt=''/>
</div>
</>:<>
<div className='imgLoad'>
<div className='UpImg'>
<div className='UpCore'>
<PlusOutlined style={{fontSize:'20px'}}/>
</div>
</div>
</div>
</>}
</label>
</Form.Item>
</>)
}
const SimpanA4=()=>{
console.log(Img1)
}
return (<>
<h1>hobi</h1>
<div className='konten'>
<Form >
<Form.List name='Hobi'>
{(fields, { add, remove }) => (<>
{fields.map((field,i)=>{
return(
<div key={field.key} className='cardAdminMod hobiList' >
<AddImg4 kd={i}/>
<Form.Item className='inputHobi' name="Hobi" {...field}>
<Input />
</Form.Item>
{fields.length > 1 ? <div className='rmHobi'><MinusCircleOutlined onClick={() => remove(field.name)} /></div>: null}
</div>)
})}
<Form.Item className='addPlusHobi'>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
Add Data
</Button>
</Form.Item>
</>)}
</Form.List>
</Form>
</div>
<div className="titleAdmin butSide">
<Button onClick={SimpanA4}>Save</Button>
</div>
</>)
}
export default Ad_abhb;
So, can anyone help me?

How to add checkbox or radio button inside the map method in react component?

How to add the checkbox or radio button inside the map method. I have created question and answer app. I need to add checkbox or radio button for the answers. Below in the card component is where the question and answer is getting printed out. How can i add the radio button in there so user can check the answer.
import React, { useState, useEffect } from "react";
import { Fragment } from "react";
import "./Survey.css";
import CreateSurvey from "../modals/CreateSurvey";
import Card from "../card/Card";
const Survey = () => {
const [modal, setModal] = useState(false);
const [surveyList, setSurveyList] = useState([]);
useEffect(() => {
let arr = localStorage.getItem("surveyList");
if (arr) {
let obj = JSON.parse(arr);
setSurveyList(obj);
}
}, []);
const deleteSurvey = (index) => {
let tempList = surveyList;
tempList.splice(index, 1);
localStorage.setItem("surveyList", JSON.stringify(tempList));
setSurveyList(tempList);
window.location.reload();
};
const toggle = () => {
setModal(!modal);
};
const updateListArray = (obj, index) => {
let tempList = surveyList;
tempList[index] = obj;
localStorage.setItem("surveyList", JSON.stringify(tempList));
setSurveyList(tempList);
window.location.reload();
};
const saveSurvey = (surveyObj) => {
let tempList = surveyList;
tempList.push(surveyObj);
localStorage.setItem("surveyList", JSON.stringify(tempList));
setSurveyList(surveyList);
setModal(false);
};
return (
<Fragment>
<div className="header text-center">
<h5>Survey</h5>
<button className="btn btn-primary" onClick={() => setModal(true)}>
Create Survey
</button>
</div>
<div className="survey-container">
{surveyList &&
surveyList.map((obj, index) => (
<Card
surveyObj={obj}
index={index}
deleteSurvey={deleteSurvey}
updateListArray={updateListArray}
/>
))}
</div>
<CreateSurvey toggle={toggle} modal={modal} save={saveSurvey} />
</Fragment>
);
};
export default Survey;
//Card.js
import React, { useState } from "react";
import "./Card.css";
const Card = ({ surveyObj, deleteSurvey, index }) => {
const [modal, setModal] = useState(false);
const toggle = () => {
setModal(!modal);
};
const deleteHandler = () => {
deleteSurvey(index);
};
return (
<div>
<div className="card-wrapper mr-5">
<div className="card-top"></div>
<div className="survey-holder">
<span className="card-header">{surveyObj.name}</span>
<p className="answer"> {surveyObj.answerOne}</p>
<div className="icons">
<i className="far fa-edit edit"></i>
<i className="fas fa-trash-alt delete" onClick={deleteHandler}></i>
</div>
</div>
</div>
</div>
);
};
export default Card;
//Createsurvey.js
import React, { useState } from "react";
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap";
import { Fragment } from "react";
const CreateSurvey = ({ modal, toggle, save }) => {
const [question, setQuestion] = useState("");
const [answerOne, setAnswerOne] = useState("");
const [answerTwo, setAnswerTwo] = useState("");
const [answerThree, setAnswerThree] = useState("");
const [answerFour, setAnswerFour] = useState("");
const changeHandler = (e) => {
const { name, value } = e.target;
if (name === "question") {
setQuestion(value);
} else {
setAnswerOne(value);
}
};
const saveHandler = (e) => {
e.preventDefault();
let surveyObj = {};
surveyObj["name"] = question;
surveyObj["answerOne"] = answerOne;
surveyObj["answerTwo"] = answerTwo;
surveyObj["answerThree"] = answerThree;
surveyObj["answerFour"] = answerFour;
save(surveyObj);
};
return (
<Fragment>
<Modal isOpen={modal} toggle={toggle}>
<ModalHeader toggle={toggle}>Create a Survey Question</ModalHeader>
<ModalBody>
<form>
<div>
<div className="form-group">
<label>Survey Questions</label>
<input
type="text"
className="form-control"
value={question}
name="question"
onChange={changeHandler}
/>
</div>
</div>
<div className="mt-2">
<label>Survey Answers</label>
<div className="form-group">
<label>Answer 1</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerOne}
name="answerOne"
onChange={changeHandler}
/>
</div>
<div className="form-group">
<label>Answer 2</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerTwo}
name="answerTwo"
onChange={changeHandler}
/>
</div>
<div className="form-group">
<label>Answer 3</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerThree}
name="answerThree"
onChange={changeHandler}
/>
</div>
<div className="form-group">
<label>Answer 4</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerFour}
name="answerFour"
onChange={changeHandler}
/>
</div>
</div>
</form>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={saveHandler}>
Create
</Button>
<Button color="secondary" onClick={toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
</Fragment>
);
};
export default CreateSurvey;
What I am understanding is that you want to add multiple component in map method. You can simply do it as:
{surveyList &&
surveyList.map((obj, index) => (
<>
<Card
surveyObj={obj}
index={index}
deleteSurvey={deleteSurvey}
updateListArray={updateListArray}
/>
<input type="checkbox" name="userchoice" />
</>
))}

React Modal Submit Form

I'm trying to print out a simple buttton clicked text whenever the submit button is click on my reactstrap modal and somehow my code doesn't do anything, not sure what I have wrong.
I have attached a picture for better visualisation , I'm using reactstrap Modal.
import React, { useState } from "react";
import { Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap";
import Button from "./Button";
// NOTICE
// Modal is brought in with it's own trigger, so import the component where you want the trigger to be.
const ModalComponent = (props) => {
const {
buttonText,
title,
actionButtonText,
cancelButtonText,
children,
className,
} = props;
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal);
const alertshow = () => {
alert("button clicked");
};
const closeBtn = (
<button className="close" onClick={toggle}>
×
</button>
);
return (
<div>
<a className="btn_link" onClick={toggle}>
{buttonText}
</a>
<form onSubmit={alertshow}>
<Modal isOpen={modal} toggle={toggle} className={className}>
<ModalHeader className=" border-0" toggle={toggle} close={closeBtn}>
{title}
</ModalHeader>
<ModalBody className="text-left border-0">
<p className="modal-label">Please enter your email address</p>
{children}
</ModalBody>
<ModalFooter className="modal-footer border-0">
<Button className="btn_secondary modal-btn" onClick={toggle}>
{cancelButtonText}
</Button>{" "}
<input
className="btn btn_primary modal-btn"
type="submit"
value={actionButtonText}
/>
</ModalFooter>
</Modal>
</form>
</div>
);
};
export default ModalComponent;
Its happening form should be part of modal not modal should be part of form. This is why its not referencing onSubmit. You need to do this:
<Modal isOpen={modal} toggle={toggle} className={className}>
<form onSubmit={alertshow}>
...rest all content
</Form>
</Modal>
Here is full code:
import React, { useState } from "react";
import "./styles.css";
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from "reactstrap";
// NOTICE
// Modal is brought in with it's own trigger, so import the component where you want the trigger to be.
const ModalComponent = (props) => {
const {
buttonText,
title,
actionButtonText,
cancelButtonText,
children,
className
} = props;
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal);
const alertshow = () => {
alert("button clicked");
};
const closeBtn = (
<button className="close" onClick={toggle}>
×
</button>
);
return (
<div>
<div onClick={toggle}>{buttonText}</div>
<Modal isOpen={modal} toggle={toggle} className={className}>
<form onSubmit={alertshow}>
<ModalHeader className=" border-0" toggle={toggle} close={closeBtn}>
{title}
</ModalHeader>
<ModalBody className="text-left border-0">
<p className="modal-label">Please enter your email address</p>
{children}
</ModalBody>
<ModalFooter className="modal-footer border-0">
<Button className="btn_secondary modal-btn" onClick={toggle}>
{cancelButtonText}
</Button>{" "}
<input
className="btn btn_primary modal-btn"
type="submit"
value={actionButtonText}
/>
</ModalFooter>
</form>
</Modal>
</div>
);
};
export default function App() {
return (
<div className="App">
<ModalComponent
title="Hello"
cancelButtonText="Cancel"
actionButtonText="Submit"
buttonText="testing"
/>
</div>
);
}
Here is the demo: https://codesandbox.io/s/fervent-bash-51lxe?file=/src/App.js:0-1826
Accepted answer doesn't work when Modal is scrollable.
Here is how to resolve the issue:
<Modal show={ show } onHide={ onClose }
scrollable={ true }
onSubmit={ handleSubmit(onSave) }
dialogAs={ FormWrappedModal }>
<Modal.Header closeButton>
<Modal.Title>some title</Modal.Title>
</Modal.Header>
<Modal.Body>some body</Modal.Body>
<Modal.Footer>some body</Modal.Footer>
</Modal>
We need to introduce custom component FormWrappedModal for that purpose:
const FormWrappedModal = ( props: any)=>{
return (
<form onSubmit={ props.onSubmit }>
<Modal.Dialog { ...props } />
</form>
);
};

Resources