I have tried to enter questionText by inputFields.questions.questionText, but it is not working
const [inputFields, setInputFields] = useState([
{
sectionName: "",
sectionDesc: "",
questions: [{ questionType: "", questionText: "" }],
},
]);
<input value={inputFields.questions.questionText} />
1)
questions and inputFields are arrays not an object so you should use index to access its value as:
value={inputFields[0].questions[0].questionText}
2) If you want to change input value on input of value then you have to use onChange here as:
CODESANDBOX LINK
function onChangeInput(e) {
setInputFields((currValue) => {
const clone = [...currValue];
clone[0].questions[0].questionText = e.target.value;
return clone;
});
}
Related
I'm working on an exercise in which I have to build a simple Quiz App,
I have a few components (such as "question", "question-list" and "add-question"),
in the "add-question" component I have a form to add a new question to the list and using a template we saw in class I'm trying to add the values the user adds to my Questions List,
I succeeded in doing that with the regular parameters by naming the relevant input with the same "name" as the parameter name,
but I'm trying to pass some values from the form into my "answers" array (which contains "text" (string), "correctAnswer"(boolean),
I tried a few things but none of them worked and the last one I tried works only for the last input I filled but not for all 4
That's my code (Including my "question" format, the "onChange" function and the form):
function AddQuestion(props) {
const [question, SetQuestion] = useState({
title: "",
description: "",
answers: [
{ id: 0, text: "", correctAnswer: false }
{ id: 1, text: "", correctAnswer: false },
{ id: 2, text: "", correctAnswer: false },
{ id: 3, text: "", correctAnswer: false }],
clicked: false});
const onChange = (e) => {
let firstAnswer, secondAnswer, thirdAnswer, fourthAnswer;
if (e.target.name === "firstAnswer") {
firstAnswer = e.target.value;
}
if (e.target.name === "secondAnswer") {
secondAnswer = e.target.value;
}
if (e.target.name === "thirdAnswer") {
thirdAnswer = e.target.value;
}
if (e.target.name === "fourthAnswer") {
fourthAnswer = e.target.value;
}
let updated = {...question, answers: {
0: { text: firstAnswer },
1: { text: secondAnswer },
2: { text: thirdAnswer},
3: { text: fourthAnswer}}
};
updated[e.target.name] = e.target.value;
SetQuestion(updated);
};
return (
<div className={style.newQuestionForm}>
<h1>Add a New Question</h1>
<label>Title: <br /> <input type="text" name="title" onInput={onChange}/></label>
<label>Description:<br/><input type="text" name="description" onInput={onChange}/></label>
<label>First Answer:<br /><input type="text" name="firstAnswer" onInput={onChange}/></label>
<label>Second Answer:<br/><input type="text" name="secondAnswer" onInput={onChange}/></label>
<label>Third Answer:<br/><input type="text" name="thirdAnswer" onInput={onChange}/></label>
<label>Fourth Answer:<br/><input type="text" name="fourthAnswer" onInput={onChange}/></label>
<div className={style.btnDiv}>
<button className={style.newQuestionBtn} onClick={() => props.onAdd(question)}>
Add New Question
</button>
</div>
</div>
);
}
There was a problem when you are trying to save final object to state.
As you can see, you are trying to convert answersfrom array to dictionary:
let updated = {...question, answers: {
0: { text: firstAnswer },
1: { text: secondAnswer },
2: { text: thirdAnswer},
3: { text: fourthAnswer}}
};
In addition, you are losing more information about the answers, like id and correctAnswer
To solve this you must continue using an array instead of dictionary.
Furthermore I improved about the logic to save info to state.
I deleted variables about the answers to use unique object, updatedQuestion. This object contains previous value from state and then you can use your conditionals to check which answer it is and change only his text
const onChange = (e) => {
let updatedQuestion = {
...question
};
if (e.target.name === "firstAnswer") {
updatedQuestion.answers[0].text = e.target.value;
}
if (e.target.name === "secondAnswer") {
updatedQuestion.answers[1].text = e.target.value;
}
if (e.target.name === "thirdAnswer") {
updatedQuestion.answers[2].text = e.target.value;
}
if (e.target.name === "fourthAnswer") {
updatedQuestion.answers[3].text = e.target.value;
}
SetQuestion(updatedQuestion);
};
Now if you try this method, when you add a question to your app, form works. You just need an extra checkbox to select which question is correct.
Let me know if you have any problem
This is created another objects dynamically when you click a button. But I want to create new object inside questions Array when I click a button.
const [inputFields, setInputFields] = useState([
{
sectionName: "",
sectionDesc: "",
questions: [{ questionType: "", questionText: "" }],
},
]);
const handleChange = (index: any, event: any) => {
const values = [...inputFields];
// #ts-ignore
values[index][event.target.name] = event.target.value;
setInputFields(values);
console.log(index, event.target.name);
};
const handleAddFields = () => {
setInputFields([
...inputFields,
{
sectionName: "",
sectionDesc: "",
questions: [{ questionType: "", questionText: "" }],
},
]);
};
First off, you are mutating state in your handleChange handler. You can avoid this using map()
const handleChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => {
setInputFields(prev => prev.map((p, i) => (
i === index
? {
...p,
[event.target.name]: event.target.value
}
: p
)));
};
As for adding to the questions array, you will need an index for which object you want to add to, then use the same technique as above to spread into that object.
const handleAddFields = (index: number) => {
setInputFields(prev => prev.map((p, i) => (
i === index
? {
...p,
questions: [...p.questions, { questionType: "", questionText: "" }]
}
: p)
));
};
Note: Using any for all parameters defeats the purpose of typing, try to use relevant types to take advantage of the type system.
The user has the possibility to enter his name. I get the name in a array. Example: ["Dilan", "Chris", "Robert"]
So what I'm trying to do is to get the name from the user, but also another value inside the array.
Example:
initialName = {
name: "",
active: "",
};
Also, I need the initalName to be inside an array.
This is what I have tried by far
const initialName = {
name: "",
active: ""
};
export default function AddingNames() {
const [names, setNames] = useState([initialName ]);
const handleAddClick = () => {
setLanguages([...names, initialName]);
};
const handleItemChanged = (event, index) => {
const value = event.target.value;
const list = [...initialName];
list[index] = value;
setNames(list);
console.log(names);
};
And this error is showed: TypeError initialName is not iterable
What I want to get from the user its just the name value in the initialName.
How can I make it work?
you can only use ... in case of iterable variable, in this case initialName is not iterable since its object
I suppose you are trying to achieve array that looks something like this:
list =
[
{name: "boo", active: "foo"},
{name: "john", active: "doe"}
]
In this case what you could do is
list[index] = {name: value, active: ""};
setNames(list)
So initial name is not iterable here as you are trying to do in usestate([]) because initial name is an object not an array. If you had an array say:
let users = [{
name: "",
active: "",
}]
Then you could iterate over the users array and access the name of a user by
let variable = user[0].name
**I have a billing form and in this i have some product details that admin can fill these details but 1 field called "BillID" i want to directly pass a variable to it that contain 'Bill ID + 1' value as a default value.
**This is My Code:-
const [BillIdFetch, setBillIdFetch] = useState();
useEffect(() => {
axios.get("http://localhost:5000/getLastBill_Id").then(( res ) => {
setBillIdFetch(res.data[0].Bill_Id + 1);
});
}, []);
console.log("===>>>> Testing BillIdFetch ",BillIdFetch) //**I check in this variable value stored perfectly.
const [Product_Details, setProduct_Details] = useState([
{
index: Math.random(),
billId : BillIdFetch, //**I want 'BllIdFetch' value pass to this state variable.
prodId: "",
qty: "",
price: "",
prod_SrNo: "",
discount_price: "",
proData_warranty: "",
},
]);
In 'BillIdFetch' i got correct id + 1 value and i also use this value for displaying Bill no. in form column. but when i set this value to 'billId' it shows like this :- {billId: undefined}
This is post request to the server.
In this a pass 'Produt_Details' array of object to it.
const config = {
header: {
"Content type": "appication/json",
},
};
const { data } = await axios.post(
"http://localhost:5000/billing_data",
{ p_value: Product_Details },
config
);
What you need to do is to check when BillIdFetch changes, and then set the correct state value for Product_Details. In your current code, the code for setting the value of Product_Details? will run before the fetching.
To solve this, use a useEffect hook with BillIdFetch as a dependency, thus, this code will run when BillIdFetch changes.
It could look something like this:
const [Product_Details, setProduct_Details] = useState([]);
const [BillIdFetch, setBillIdFetch] = useState();
useEffect(() => {
axios.get("http://localhost:5000/getLastBill_Id").then(( res ) => {
setBillIdFetch(res.data[0].Bill_Id + 1);
});
}, []);
useEffect(() => {
if (billIdFetch === undefined) return;
setProduct_Details([{
index: Math.random(),
billId : BillIdFetch,
prodId: "",
qty: "",
price: "",
prod_SrNo: "",
discount_price: "",
proData_warranty: "",
}])
}, [billIdFetch])
I have array of objects where i need to an key value
useState :
const [row, setRow] = useState([{ nameofthework: "", schedulerefNo: "", unitprice: "", qty: "", uom: "", gst: "", total: "" }]);
The form input change function
const handleInputChange = (e, index) => {
const { name, value } = e.target;
const list = [...row];
list[index][name] = value;
setRow(list);
console.log(row); // Prints out the each row object into and array of objects
};
const handleQty = (e) => {
const scheduleNumberForQuantity = e.target.value;
projectScheduleNumber?.filter((v) => {
if(v["Schedule No"] === scheduleNumberForQuantity ) {
setScheduleQuantity(v["LOA Qty"]); // return only integer example 1000
}
})
}
How to add handleQty value to row state ?
I think that you need declare the state like a function instead of array of objects key value. It will allow setRow to be managed as function in any moment inside of the function component.
const [row, setRow] = useState<any>();
With <any> allows save anything. So you could apply a strong type like:
const [row, setRow] = useState<()=>void>();
or in you case
const [row, setRow] = useState<(e: any)=>void>();
I hope it is useful for you.