I am trying to pass a function to a react component but it say that it is not a function. I can console log the props and I have set it up, as far as i can tell, the same way I have always done. Please help, thanks!
EDIT: I get the same error when i try to test the onSubmit function, too
<div className="bookshelf">
<Searchbar
handleChange={onChange}
addInputClass={"searchbar_mobile_input"}
addBtnClass={"searchbar_mobile_btn"}
/>
<div className="bookshelf_heading_container">
<h2 className="bookshelf__heading">
Release the Kraken of Knowledge!
</h2>
</div>
import React, {Fragment} from "react";
const SearchBar = ({ addBtnClass, addInputClass, handleChange }) => {
console.log(handleChange)
return (
<Fragment>
<form className="search__form__input" onSubmit={() => handleSubmit(e)}>
<input
type="text"
placeholder="Search by Title/Author"
className={`searchbar__input ${addInputClass}`}
name="search"
onChange={(e) => handleChange(e)}
></input>
<button type="submit" className={`btn ${addBtnClass}`}>
Search
</button>
</form>
</Fragment>
);
};
export default SearchBar;
Here is an example that should help you. You should be able to take this simplified example and work out how to apply it to your example. I would've used your code but it was incomplete and no sandbox was provided.
import React from "react";
export default function AppLogic() {
const [readValue, writeValue] = React.useState("");
const handleChange = (e) => writeValue(e.target.value);
const handleSubmit = (e) => {
e.preventDefault();
alert("Submitted");
};
const props = { readValue, handleChange, handleSubmit };
return <AppView {...props} />;
}
function AppView({ handleSubmit, handleChange, readValue }) {
return (
<div className="App">
<h1>Name</h1>
<form onSubmit={handleSubmit}>
<input onChange={handleChange} value={readValue} />
<input type="submit" />
</form>
<p>{readValue}</p>
</div>
);
}
Related
I have a ready-made form in React
I'm trying to add a captcha to it but it would seem that with the only correct option the captcha reload infinity loops
I didt think that in such a simple task in React there could be so many problems
import { GoogleReCaptchaProvider, GoogleReCaptcha } from 'react-google-recaptcha-v3'
type Props = {
onSubmit: (values: AuthRequest) => Promise<AuthResponse>
}
function AuthForm(props: Props) {
const [token, setToken] = useState('')
return (
<div className={cn('container')}>
<GoogleReCaptchaProvider reCaptchaKey="[key]">
<Form
onSubmit={handlers.submit}
render={({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
<FormField name={'email'} />
<div>
<FormField name={'password'} />
</div>
<GoogleReCaptcha
onVerify={(token) => {
setToken(token)
}}
/>
<div>
<Button type="submit">Submit</Button>
</div>
</form>
)}
/>
</GoogleReCaptchaProvider>
</div>
)
}
export { AuthForm }
I solved it like this
import { GoogleReCaptchaProvider, GoogleReCaptcha } from 'react-google-recaptcha-v3'
type Props = {
onSubmit: (values: AuthRequest) => Promise<AuthResponse>
}
function AuthForm(props: Props) {
const [token, setToken] = useState('')
const verifyRecaptchaCallback = React.useCallback((token) => {
setToken(token)
}, []);
return (
<div className={cn('container')}>
<GoogleReCaptchaProvider reCaptchaKey="[key]">
<Form
onSubmit={handlers.submit}
render={({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
<FormField name={'email'} />
<div>
<FormField name={'password'} />
</div>
<GoogleReCaptcha
onVerify={verifyRecaptchaCallback}
/>
<div>
<Button type="submit">Submit</Button>
</div>
</form>
)}
/>
</GoogleReCaptchaProvider>
</div>
)
}
export { AuthForm }
I am trying send only one of my form's id to my handleSubmit function in react. My forms are created via a map function, which creates a form for each data enter from my DB. My handleSubmit function currently take in an event and outputs it to the console log. When running the code, I get all of my id's instead of one. Any help?
Here is my code:
import React, { useRef, useState } from 'react';
export const Movie = ({listOfReviews}) =>{
const handleSubmit = (event) => {
console.log(event)
}
return (
<>
<h1>Your reviews:</h1>
{listOfReviews.map(review =>{
return(
<form onSubmit={handleSubmit(review.id)}>
<label>
Movieid:{review.movieid}
<input type="text" value={review.id} readonly="readonly" ></input>
<input type="text" value={review.comment}></input>
<input type="submit" value="Delete"></input>
</label>
</form>
)
})}
</>
)
}
You have a simple error in your onSubmit callback. Instead of calling handleSubmit in the callback prop, you should instead define an inline function that calls handleSubmit.
Like this:
<form onSubmit={() => handleSubmit(review.id)}>
Full code:
import React, { useRef, useState } from 'react';
export const Movie = ({ listOfReviews }) => {
const handleSubmit = (id) => {
console.log(id);
};
return (
<>
<h1>Your reviews:</h1>
{listOfReviews.map((review) => {
return (
<form onSubmit={() => handleSubmit(review.id)}>
<label>
Movieid:{review.movieid}
<input type="text" value={review.id} readonly="readonly"></input>
<input type="text" value={review.comment}></input>
<input type="submit" value="Delete"></input>
</label>
</form>
);
})}
</>
);
};
I have a with the following structure in react...
<form>
<div>
<label>Name</label>
<input />
</div>
<div>
<label>Age</label>
<input />
</div>
<div>
<label>Gender</label>
<input />
</div>
<AddressComponent />
<button type='submit'>
Submit
</button>
</form>
Does anyone know if there is a way for me to pass the AddressComponent data up to the parent form component onSubmit? The AddressComponent has a lot of state to manage and a load of functions and it appears a few more times across my website and so I don't want to keep repeating the same code over and over again.
Anyone know if there's a way for me to pass the AddressComponent state up to the parent form component onSubmit?
you can use ref to get access to the child functions so:
const AddressComponent = ({}, ref) => {
const [data, setData] = useState();
useImperativeHandle(ref, () => ({
getData: getData,
}));
const getData = () => {
return data;
}
return <div></div>;
};
export default React.forwardRef(AddressComponent);
and you can get data in your parent and in submit like this:
const ParentComponent = () => {
const AddressRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
const data = AddressRef.current.getData();
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>Name</label>
<input />
</div>
<div>
<label>Age</label>
<input />
</div>
<div>
<label>Gender</label>
<input />
</div>
<AddressComponent ref={AddressRef} />
<button type='submit'>
Submit
</button>
</form>
)
}
I have a main App component that has a form and another component that also renders a separate form. I want the second form to submit correctly using its separate handleSecondSubmit function, but it does not seem to use it.
Here's the full code and a StackBlitz: Stackblitz Demo
import React from "react";
import { useForm } from "react-hook-form";
const SecondForm = () => {
const { handleSubmit, register } = useForm();
const handleSecondSubmit = e => {
e.preventDefault();
console.log("2nd form");
};
return (
<form onSubmit={e => handleSubmit(handleSecondSubmit)}>
<input name="test" type="text" ref={register({ required: true })} />
<input type="submit" />
</form>
);
};
const App = () => {
const { register, handleSubmit, watch, errors } = useForm();
const onSubmit = data => console.log(data);
console.log(watch("example"));
return (
<>
<form onSubmit={handleSubmit(onSubmit)}>
<input name="example" defaultValue="test" ref={register} />
<input name="exampleRequired" ref={register({ required: true })} />
{errors.exampleRequired && <span>This field is required</span>}
<input type="submit" />
</form>
<SecondForm />
</>
);
};
export default App;
Can someone explain what's happening here? Thank you
You need to call the handleSubmit directly when applying the handler, and the signature for the returned function has the event as the second argument (the first being the data)
const SecondForm = () => {
const { handleSubmit, register } = useForm();
const handleSecondSubmit = (data, e) => {
e.preventDefault();
console.log("2nd form", data);
};
return (
<form onSubmit={handleSubmit(handleSecondSubmit)}>
<input name="test" type="text" ref={register({ required: true })} />
<input type="submit" />
</form>
);
};
https://stackblitz.com/edit/react-v7cdfh
try this :
return (
<form onSubmit={e => handleSubmit(handleSecondSubmit(e))}>
<input name="test" type="text" ref={register({ required: true })} />
<input type="submit" />
</form>
);
};
you forgot to pass e to handleSecondSubmit(e)
Seems you need to pass the onSubmit event object through to your second form's handler.
onSubmit={e => handleSubmit(handleSecondSubmit(e))}
https://stackblitz.com/edit/react-fduvdv
I am aiming for new tasks to show as user clicks "add task", simple I know, but still learning react.
My goal was to use a ternary operator until its no longer null, and then map through the array each time a user clicks add task.
Issue:
I believe the renderTasks array isn't set by the time it tries to map over it, I get an error...
renderTasks.map is not a function
Is there a way I could utilize the useEffect for what I am trying to do, or any better ideas that could help? Thanks
Here's the code snippet of App.js
function App() {
const [tasks, setTasks] = useState([]);
const [renderTasks, setRenderTasks] = useState(null);
const handleAddTask = () => {
setRenderTasks(tasks);
};
const handleOnChange = (e) => {
setTasks({
...tasks,
[e.target.name]: e.target.value,
});
};
return (
<>
<div className="overview">
<label className="my-todos">My Todos</label>
<div className="input-div">
<div className="input-container">
<label className="title-desc">Title</label>
<input
name="title"
onChange={handleOnChange}
className="input-values"
type="text"
></input>
</div>
<div className="input-container">
<label className="title-desc">Description</label>
<input
name="description"
onChange={handleOnChange}
className="input-values"
type="text"
></input>
</div>
<button onClick={handleAddTask} className="add-task">
Add Task
</button>
</div>
{renderTasks !== null ? (
<ul>
{renderTasks.map((x) => {
return <li>{x.title - x.description}</li>;
})}
</ul>
) : null}
</div>
</>
);
}
export default App;
There were few issues in your implementation like how you destructing tasks, trying to access an object as an array and abusing the useState. You don't need useEffect or two useState to do the trick.
import React from "react";
import React, { useState } from 'react';
import "./style.css";
function App() {
const [tasks, setTasks] = useState([]);
const task = {};
const handleOnChange = (e) => {
task[e.target.name] = e.target.value;
};
const onClickHandler = (e)=>{
(task.title) && setTasks( [...tasks, task]);
}
return (
<>
<div className="overview">
<label className="my-todos">My Todos</label>
<div className="input-div">
<div className="input-container">
<label className="title-desc">Title</label>
<input
name="title"
onChange={handleOnChange}
className="input-values"
type="text"
></input>
</div>
<div className="input-container">
<label className="title-desc">Description</label>
<input
name="description"
onChange={handleOnChange}
className="input-values"
type="text"
></input>
</div>
<button onClick={onClickHandler} className="add-task">
Add Task
</button>
</div>
<ul>
{tasks.map((x) => {return <li>{x.title} - {x.description}</li> })}
</ul>
</div>
</>
);
}
export default App;
Even though you are initialising tasks to be an array, in handleOnChange you are setting it to an Object like this -
setTasks({
...tasks,
[e.target.name]: e.target.value,
});
This same tasks object you are trying to set for renderTasks in handleAddTask. So renderTasks is assigned to an Object and not an array and only arrays have map function and hence you are facing the issue renderTasks.map is not a function error
Try doing
Object.keys(renderTasks).map((x) => {
return <li>{x.title - x.description}</li>;
})