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?
Related
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
I am Learning React and i want to work with forms. Initally i gave value "hello" in the form but i couldn't erase it and type anything in the form.
import { React, useState } from "react";
const App = () => {
const [num, setNum] = useState(0);
const handleClick = () => {
setNum(num + 1);
};
const mew = () => {
console.log("submiited");
};
return (
<div className="bg-green-500 text-center">
<h1 className="bg-red-200">
🎰 Welcome to <span> Slot Machine game</span> 🎰{" "}
</h1>
<h1></h1>
<button
onClick={handleClick}
className="bg-red-200 w-92 mt-4 mb-4 rounded-full p-2 text-center"
>
Click
</button>
<h1>{num}</h1>
<form className="form" onSubmit={mew}>
<div className="form-control">
<label htmlFor="firstName">Name : </label>
<input
className="mb-2"
type="text"
name="txt"
value="Hello"
onChange={(e) => {
console.log(e.target.value);
}}
/>
</div>
</form>
</div>
);
};
export default App;
This could be work
import React, { useState } from 'react';
import './style.css';
const App = () => {
const [num, setNum] = useState(0);
const [name, setName] = useState('Hello');
const handleClick = () => {
setNum(num + 1);
};
const mew = () => {
console.log('submiited');
};
return (
<div className="bg-green-500 text-center">
<h1 className="bg-red-200">
🎰 Welcome to <span> Slot Machine game</span> 🎰{' '}
</h1>
<h1></h1>
<button
onClick={handleClick}
className="bg-red-200 w-92 mt-4 mb-4 rounded-full p-2 text-center"
>
Click
</button>
<h1>{num}</h1>
<form className="form" onSubmit={mew}>
<div className="form-control">
<label htmlFor="firstName">Name : </label>
<input
className="mb-2"
type="text"
name="txt"
value={name}
onChange={(e) => {
setName(e.target.value);
}}
/>
</div>
</form>
</div>
);
};
export default App;
You are trying to use controlled inputs but not doing that correctly. When using controlled inputs, you feed the value in the input field, and it is your responsibility to change the value.
useState can help you do this.
const App = () => {
const [num, setNum] = useState(0);
const [textValue , setTextValue] = useState("hello");
const handleClick = () => {
setNum(num + 1);
};
const changeText = (e) => {
setTextValue(e.target.value);
}
const mew = () => {
console.log("submiited");
};
return (
<div className="bg-green-500 text-center">
<h1 className="bg-red-200">
🎰 Welcome to <span> Slot Machine game</span> 🎰{" "}
</h1>
<h1></h1>
<button
onClick={handleClick}
className="bg-red-200 w-92 mt-4 mb-4 rounded-full p-2 text-center"
>
Click
</button>
<h1>{num}</h1>
<form className="form" onSubmit={mew}>
<div className="form-control">
<label htmlFor="firstName">Name : </label>
<input
className="mb-2"
type="text"
name="txt"
value={textValue}
onChange={changeText}
/>
</div>
</form>
</div>
);
};
export default App;
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" />
</>
))}
I'm trying to create an app that when the user clicks on create button a survey question with four answers gets created. The goal is that in a single list the user can maximum add up to 4 questions and a minimum of 1 question. So when the user tries to add another question after the 4th question a new survey list should be created. So one survey list can contain a maximum of four questions.
//Survey.js
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 surveyListArray = [];
// while (surveyList.length > 0) {
// surveyListArray.push(surveyList.splice(0, 3));
// }
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}
>
<input type="radio" name="answerOne" />
</Card>
))}
</div>
<CreateSurvey toggle={toggle} modal={modal} save={saveSurvey} />
</Fragment>
);
};
export default Survey;
//Card.js
import React, { useState } from "react";
import "./Card.css";
import EditSurvey from "../modals/EditSurvey";
const Card = ({ surveyObj, deleteSurvey, index, updateListArray }) => {
const [modal, setModal] = useState(false);
const toggle = () => {
setModal(!modal);
};
const updateSurvey = (obj) => {
updateListArray(obj, index);
};
const deleteHandler = () => {
deleteSurvey(index);
};
return (
<div>
<div className="card-wrapper mr-5">
<div className="card-top"></div>
<div className="survey-holder">
<span className="card-headers">{surveyObj.name}</span>
<span className="check">
<input type="radio" className="radio" />
<p className="answer"> {surveyObj.answerOne}</p>
</span>
<span className="check">
<input type="radio" className="radio" />
<p className="answer"> {surveyObj.answerTwo}</p>
</span>
<span className="check">
<input type="radio" className="radio" />
<p className="answer"> {surveyObj.answerThree}</p>
</span>
<span className="check">
<input type="radio" className="radio" />
<p className="answer"> {surveyObj.answerFour}</p>
</span>
<div className="icons">
<i className="far fa-edit edit" onClick={() => setModal(true)}></i>
<i className="fas fa-trash-alt delete" onClick={deleteHandler}></i>
</div>
</div>
<EditSurvey
modal={modal}
toggle={toggle}
updateSurvey={updateSurvey}
surveyObj={surveyObj}
/>
</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 if (name === "answerOne") {
setAnswerOne(value);
} else if (name === "answerTwo") {
setAnswerTwo(value);
} else if (name === "answerThree") {
setAnswerThree(value);
} else {
setAnswerFour(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;
Updated CodeSandbox link here
The Add transaction button is not rendering the transaction list in transaction history container
This piece of code {transaction && transaction.map(trans).... is rendering the app UI but the Add transaction button is not generating the Transaction component dynamically in transaction history container}
import React from 'react';
const AddTransaction =
({item,amount,setItem,setAmount,transaction,setTransaction})
=> {
const onSubmit = (e) => {
e.preventDefault();
setTransaction([...transaction,
{
text: item,
amount: amount,
id: Math.floor(Math.random()*1000),
}
] );
setItem('');
setAmount('');
}
return (
<div className='addtransaction-container'>
<div className='add-trans-header'>
<h4>Add New Transaction</h4>
</div>
<form>
<div className="form-control">
<label htmlFor="text">Text</label>
<input type="text" value={item}
onChange={(e) => setItem(e.target.value)}
placeholder="Enter text..." />
</div>
<div className="form-control">
<label htmlFor="amount"
>Amount <br />
(negative - expense, positive - income)
</label>
<input type="number" value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="Enter amount..." />
</div>
<button type='button' onClick={onSubmit}
value='submit'
className="btn">
Add transaction
</button>
</form>
</div>
);
}
export default AddTransaction;
The map function is not rendering the Transaction
component in TransactionList.js file
import React from 'react'
import './App.css';
import Transaction from './Transaction.js';
const TransactionList = ({text,transaction,amount}) => {
return (
<div className='transactionlist-container'>
<div className='transactionlist-header-container'>
<h4>
Transaction History
</h4>
</div>
<ul>
<li>
{ transaction.map(trans =>
<Transaction
amount={transaction.amount}
text={transaction.text}
key={transaction.id} />
)}
</li>
</ul>
</div>
)
}
export default TransactionList;
My Transaction.js file have a ul list with the input text and amount but the component is not rendering in the app UI.
import React from 'react'
const Transaction = ({transaction,text,amount}) => {
return (
<div className='transaction'>
{text}<span>{amount}</span>
</div>
)
}
export default Transaction;
I have recreated the app, which is working without any issue.
Here is the link to the working demo: StackBlitz
import React, { useState, useEffect } from "react";
import TransactionList from "./TransactionList";
import AddTransaction from "./AddTransaction";
const App = () => {
const [transaction, setTransaction] = useState([]);
const handleTransaction = value => {
setTransaction([...transaction, value]);
};
const expenseList = transaction.filter(trans => Number(trans.amount) < 0);
const expense = expenseList.reduce(
(acc, curr) => acc + Number(curr.amount),
0
);
const amountList = transaction.filter(trans => Number(trans.amount) > 0);
const amount = amountList.reduce((acc, curr) => acc + Number(curr.amount), 0);
useEffect(() => {
console.log("From app:", transaction);
}, [transaction]);
return (
<div className="transactionlist-container">
<div>
<span>income: {JSON.stringify(amount)}</span>{" "}
<span> total expense: {JSON.stringify(expense)}</span>
<span> balance: {amount + expense}</span>
</div>
<TransactionList transaction={transaction} />
<AddTransaction
transaction={transaction}
handleTransaction={handleTransaction}
/>
</div>
);
};
export default App;
import React from "react";
import Transaction from "./Transaction";
const TransactionList = ({ transaction }) => {
console.log("from tl:", transaction);
return (
<div className="transactionlist-container">
<div className="transactionlist-header-container">
<h4>Transaction History</h4>
</div>
{transaction.map(trans => (
<Transaction amount={trans.amount} text={trans.text} key={trans.id} />
))}
</div>
);
};
export default TransactionList;
import React from "react";
const Transaction = ({ text, amount }) => {
return (
<div className="transaction">
{text}
<span>{amount}</span>
</div>
);
};
export default Transaction;
import React,{useState} from "react"
const AddTransaction =
({handleTransaction})
=> {
const [item,setItem] = useState("")
const [amount, setAmount] = useState(0)
const onSubmit = (e) => {
e.preventDefault();
handleTransaction(
{
text: item,
amount: amount,
id: Math.floor(Math.random()*1000),
}
);
setItem('');
setAmount('');
}
return (
<div
className="inputBox"
>
<div className='add-trans-header'>
<h4>Add New Transaction</h4>
</div>
<form>
<div className="form-control">
<label htmlFor="text">Text</label>
<input type="text" value={item}
onChange={(e) => setItem(e.target.value)}
placeholder="Enter text..." />
</div>
<div className="form-control">
<label htmlFor="amount"
>Amount <br />
(negative - expense, positive - income)
</label>
<input type="number" value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="Enter amount..." />
</div>
<button type='button' onClick={onSubmit}
value='submit'
className="btn">
Add transaction
</button>
</form>
</div>
);
}
export default AddTransaction;