When I submit text in the form, I want to be able to see that text in state via console.log.
I added a console.log to trigger directly after state has been added, but I don't see anything in my console, what am I doing wrong?
What I would like to see: I submit "test1" then I submit "test2", I then want to see in my console "test1, test2" in state.
import React, { useState } from 'react';
import './App.css';
function App() {
return (
<div>
<Field />
</div>
);
}
function Field(){
const [toDoItem, setToDoItem] = useState('');
const addToDoItem = (event) => {
setToDoItem(event.target.value), function(){
console.log(toDoItem)
}
}
return (
<form>
<input type="text" value={toDoItem} onChange={addToDoItem}/>
<input type="submit" value="Add" />
</form>
);
}
export default App;
You can log the change in states using a useEffect
I'd suggest making a helper function if you tend to do it often:
function useLog(name, property) {
useEffect(() => console.log(name, property), [name, property]);
}
Which you'd use as follows:
useLog('toDoItem', toDoItem);
I set up an example where the toDoItem is logged as it changes and when you submit, it also logs the change in a todoItems array
const { useState, useEffect } = React;
function useLog(name, property) {
useEffect(() => console.log(name, property), [name, property]);
}
function App() {
return (
<div>
<Field />
</div>
);
}
function Field() {
const [toDoItem, setToDoItem] = useState('');
useLog('toDoItem', toDoItem);
const [todos, setTodos] = useState([]);
useLog('todos', todos);
const changeTodo = (event) => {
setToDoItem(event.target.value);
};
const addTodoItem = (event) => {
event.preventDefault();
setTodos((prev) => prev.concat(toDoItem));
setToDoItem('');
};
return (
<form onSubmit={addTodoItem}>
<input type="text" value={toDoItem} onChange={changeTodo} />
<input type="submit" value="Add" />
</form>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"/>
useState doesn't provide callback after setting value. You can use useEffect instead.
React.useEffect(() => {
console.log(toDoItem);
}, [toDoItem]);
EDIT
It seems like that you want to get toDoItem value on submit. The problem is that the page is reloaded when form is submitted. You can use event.prefentDefault() to stop refreshing on form submission.
<form onSubmit={onSubmit}>
const onSubmit = (event) => {
event.preventDefault()
console.log(toDoItem)
}
import React, { useState } from 'react';
import './App.css';
function App() {
return (
<div>
<Field />
</div>
);
}
function Field(){
const [toDoItem, setToDoItem] = useStateWithCallback('', toDoItem => {
console.log(toDoItem);
});
const addToDoItem = (event) => {
setToDoItem(event.target.value);
}
return (
<form>
<input type="text" value={toDoItem} onChange={addToDoItem}/>
<input type="submit" value="Add" />
</form>
);
}
export default App;
Related
I have a form where i need to save the values as an array:
function App() {
const {
setValue,
register,
handleSubmit,
watch,
formState: { errors }
} = useForm();
const onSubmit = (data) => {
console.log(data, "submit");
}; // your form submit function which will invoke after successful validation
const allValues = watch("example") || [];
console.log(allValues);
return (
<form onSubmit={handleSubmit(onSubmit)}>
{[1, 2, 3].map((v, index) => {
return (
<input value={v} type="checkbox" {...register(`example[${index}]`)} />
);
})}
<input
onChange={(e) => {
setValue("example", e.target.value);
}}
/>
<input type="submit" />
</form>
);
}
Here: setValue("example", e.target.value); i want to set my text input value inside the result, so when i add check some checkboxes like 1 and 2 and also add test value in text input, when i will save i need to get the next result [1,2,'test']. If there is not a value in text input i should't add anything in the array. question: How to solve the issue? Now if i add test in array i get [t,e,s,t]. demo: https://codesandbox.io/s/react-hook-form-get-started-forked-q2xhj5?file=/src/index.js:129-840
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { useForm } from "react-hook-form";
import "./styles.css";
function App() {
const { setValue, getValues, register, handleSubmit } = useForm();
const [inputValue, setInputValue] = useState("");
const onSubmit = (data) => {
if (inputValue) setValue("example", [...getValues().example, inputValue]);
console.log(getValues().example);
}; // your form submit function which will invoke after successful validation
return (
<form onSubmit={handleSubmit(onSubmit)}>
{[1, 2, 3].map((v, index) => {
return (
<input value={v} type="checkbox" {...register(`example[${index}]`)} />
);
})}
<input
value={inputValue}
onChange={(e) => {
setInputValue(e.target.value);
}}
/>
<input type="submit" />
</form>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
This is my solution. Some changes I made:
I only add the input value to the "example" array onSubmit, not onChange.
I made the input controlled, giving it a value property inputValue, and setting it in the onChange handler
I made use of getValues function, to obtain the current elements of example array. Then I used setValue with the spread operator to add at the end of the array.
Feel free to ask me further questions!
--Ado
Edit 1: turns out I got it wrong, you don't want to add the input value to example every time on submit. Here is my new solution:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { useForm } from "react-hook-form";
import "./styles.css";
function App() {
const { getValues, register, handleSubmit } = useForm();
const onSubmit = (data) => {
console.log(getValues().example);
}; // your form submit function which will invoke after successful validation
const checkboxes = [1, 2, 3];
return (
<form onSubmit={handleSubmit(onSubmit)}>
{checkboxes.map((v, index) => {
return (
<input value={v} type="checkbox" {...register(`example[${index}]`)} />
);
})}
<input
{...register(`example[${checkboxes.length}]`)}
/>
<input type="submit" />
</form>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
I am trying to output data from an input field as list elements. However, I always get the error message "addData is not a function" just before the finish line. Does anyone happen to have an idea where my error is? I have the feeling that the majority should be correct.
Thanks to all of you!
Heres my App.js
import "./styles.css";
import Form from "/src/Form";
import { React, useState } from "react";
export default function App() {
const [displayData, setDisplayData] = useState([]);
const addData = (formData) => {
setDisplayData([...displayData, { formData: formData }]);
};
return (
<div className="App">
<ul>
{displayData.map((data) => (
<li data={data.formData} />
))}
</ul>
<Form formData={addData} />
</div>
);
}
And this is my Form.js
import { React, useState } from "react";
const Form = ({ addData }) => {
const [formData, setFormData] = useState("");
const handleSubmit = (event) => {
event.preventDefault();
addData(formData);
};
return (
<div>
<form onSubmit={handleSubmit}>
<label>Hier kommt die neue Form:</label>
<br />
<input
placeholder="Vor- und Nachname"
type="text"
value={formData}
required
onChange={(event) => setFormData(event.target.value)}
></input>
<br />
<input placeholder="Hausnummer und PLZ" type="text" required></input>
<br />
<button>Submit</button>
</form>
</div>
);
};
export default Form;
The prop you're passing is called formData:
<Form formData={addData} />
But the component is expecting it as addData:
const Form = ({ addData }) => {
Change one to match the other. Since the component already has a state variable called formData, it's probably easier to change the usage:
<Form addData={addData} />
On one page I have two inputs and a button, after clicking on the button goes to the second page, how do I get data from the inputs on the second page?
navigate(path, { state: { input_value: value }}) ?
index.js
import './App.css';
function App() {
return (
<div className='App'>
<header className='App-header'>
<input type='text' placeholder='Name'/>
<input type='text' placeholder='Surname'/>
<button type='submit'>Send</button>
</header>
</div>
);
}
export default App;
getData.js
export const getData = () => {
return (
<div>
<h1>Name:</h1>
<h1>Surname:</h1>
</div>
)
};
You can have a state variable in the App component and then pass the state as a prop to GetData:
import './App.css';
import { useState, useRef } from "react";
function App() {
const nameInput = useRef(null);
const surNameInput = useRef(null);
const [fullName, setFullName] = useState({
name: "",
surName: ""
});
const sendData = () => {
// you can do some input validation here
setFullName({
name: nameInput.current.value,
surName: surNameInput.current.value,
});
}
return (
<div className='App'>
<header className='App-header'>
<input type='text' placeholder='Name'
ref={nameInput}
/>
<input type='text' placeholder='Surname'
ref={surNameInput}
/>
<button onClick={sendData}>Send</button>
</header>
<!-- some more markup here -->
</div>
);
}
export default App;
Here's how you pass your data to GetData component:
<GetData fullName={fullName} />
And then in your GetData component you get the passed props and display them:
export const GetData = (fullName) => {
return (
<div>
<h1>Name: {fullName.name}</h1>
<h1>Surname: {fullName.surName}</h1>
</div>
)
};
You can read more about hooks like useState and useRef here
So this might be Part 1 of an answer.
Taking the code you have, I've put the fields in form tag, then called handleSubmit from the built in onSubmit that is called when you click a button of type='submit' inside a form.
The values is taken from the event parameter (e) of the onSubmit (you can identify these by the 'name' attribute on the input tags) and then I am using useState hook to store the two values.
This would be where part one ends. You have the data, and you can see how it is passed to the GetDate component (the deconstructed props {name, surname} that are passed in.
From there, you should follow the documentation for your chosen router and, if you run into trouble, post the code you've tried and I can continue to help.
https://v5.reactrouter.com/web/guides/quick-start
import React, { useState } from 'react';
import { GetData } from './GetData';
export function App() {
const [theName, setTheName] = useState('');
const [theSurname, setTheSurname] = useState('');
const handleSubmit = (e) => {
setTheName(e.target.name.value);
setTheSurname(e.target.surname.value);
e.preventDefault();
}
return (
<div className='App'>
<header className='App-header'>
<form onSubmit={handleSubmit}>
<input type='text' placeholder='Name' name='name'/>
<input type='text' placeholder='Surname' name='surname'/>
<button type='submit'>Send</button>
</form>
</header>
<GetData name={theName} surname={theSurname} />
</div>
);
}
export default App;
Here is a component like your getData function.
I've added it to the App component, just so you can see the values being displayed, but for what you are looking for, you will need to read the documentation for react-router-dom
import React from "react";
export const GetData = ({name, surname}) => {
return (
<div>
<h1>Name:{name}</h1>
<h1>Surname:{surname}</h1>
</div>
)
};
Hi I am new to React and I just can't wrap my head around some basic things.
One of these things is the following.
Why does the state of itemData change when calling the function with onChange on the textarea element as in this example:
import React, { useEffect, useState } from "react";
function Createitem() {
const [itemData, setitemData] = useState([]);
const handleitemData = (e) => {
setitemData({
itemTime: Date.now(),
itemText: e.target.value,
});
};
useEffect(() => {
console.log("item", itemData);
}, [itemData]);
return (
<div className="itemBox">
<div>
<form>
<textarea
onChange={handleitemData}
placeholder="What you have in mind ..."
></textarea>
<button type="submit">item</button>
</form>
</div>
</div>
);
}
export default Createitem;
But not when calling the function with onSubmit on the form element as in this example:
import React, { useEffect, useState } from "react";
function Createitem() {
const [itemData, setitemData] = useState([]);
const handleitemData = (e) => {
setitemData({
itemTime: Date.now(),
itemText: e.target.value,
});
};
useEffect(() => {
console.log("item", itemData);
}, [itemData]);
return (
<div className="itemBox">
<div>
<form onSubmit={handleitemData}>
<textarea placeholder="What you have in mind ..."></textarea>
<button type="submit">item</button>
</form>
</div>
</div>
);
}
export default Createitem;
I know the React way is if that does not work try something else but I am trying to actually understand what is going on.
I apreciate your response.
You must prevent the default behavior of the browser on submit:
import React, { useEffect, useState } from "react";
function Createitem() {
const [itemData, setitemData] = useState([]);
const handleitemData = (e) => {
//The line below is necessary
e.preventDefault()
setitemData({
itemTime: Date.now(),
itemText: e.target.value,
});
};
useEffect(() => {
console.log("item", itemData);
}, [itemData]);
return (
<div className="itemBox">
<div>
<form onSubmit={handleitemData}>
<textarea placeholder="What you have in mind ..."></textarea>
<button type="submit">item</button>
</form>
</div>
</div>
);
}
export default Createitem;
attached is a sandbox to see it in action https://codesandbox.io/s/infallible-lederberg-3oj1w?file=/src/App.js:0-630
I'm new to react and I'm trying to edit an input field after I prefilled its value with an object value from my database, so what should I put on onChange if value is value={data.info}? because I cannot type or change the initial value. I've watched a lot of tutorials but this. and props are very confusing to me
import React, { useState } from 'react';
import { useParams } from 'react-router-dom';
import useAsync from '../useAsync';
export default function Details() {
const url = 'https://..';
const { index } = useParams();
const { data } = useAsync(url + index);
const [state, setState] = useState(false);
const showForm = () => {
return (
<div>
<form>
<input type="text" value={data.info} onChange={} />
</form>
</div>
)
}
return (
<div className="details" >
{data && <p key={index}>{data.info}</p>}
<button onClick={() => setState({ showForm: true })}>Edit</button>
{state.showForm ? showForm() : null}
</div>
)
}
You can add "default value" to your state. So you can move the data value to your useState(false) so useState(data)
import React, { useState } from "react";
const App = () => {
const [formInput, setFormInput] = useState(""); // You can add your "data" as default value
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>formInput Value {formInput}</h2>
<input
type="text"
value={formInput}
onChange={(e) => setFormInput(e.target.value)} // You need to set the state with the onchange value from the input
/>
</div>
);
};
export default App;
Link to CodeSandbox