How to bind two methods simultaneously in reactjs - reactjs

I have two components - one is App.js and other is Login.js and i have placed an input field and button in the Login and methods are placed in App.js. So i want to bind those methods by calling the Login component from the App.js.
Kindly review the logic in Login> tags as whenever i click on Flick button , it consoles the value for a second and then page refreshes automatically.
App.js
handleFlick(e){
console.log("Oho");
e.preventdefault()
}
handleChange(e) {
this.setState({
name: e.target.value
})
render() {
return (
<div>
<h1>{this.state.name} </h1><br></br>
<p>first component</p>
<Login
handleChange={this.handleChange.bind(this)}
handleFlick={this.handleFlick.bind(this)}
></Login>
Login.js
<div>
<form>
<input type="text" placeholder="enter name" onChange={(e) => { this.props.handleChange(e) }}></input>
<button onClick={(e) => { this.props.handleFlick(e) }}>Flick</button>
</form>
</div>

Change this:
<button onClick={(e) => { this.props.handleFlick(e) }}>Flick</button>
For this:
<button onClick={(e) => { this.props.handleFlick(e); e.preventDefault() }}>Flick</button>
type submit will by default refresh the page when sended

Related

Send values from one browser tab to another in nextjs and populate formik form

I have a form in next with a single input e.g. name on my page. On submit I would like the browser to open a new tab which contains a form with more inputs e.g. name, address, age. How can I pre-populate the name in the new tab?
I was considering the useContext hook but as far as I can tell that does not work across tabs. Do I need to use Redux at this point?
Edit: My attempt using localStorage so far:
// User inputs name which on submit is
// saved to local storage and /register page is opened
const Home: NextPage = () => {
return (
<Formik
initialValues={{ name: '' }}
onSubmit={(values) =>
localStorage.setItem('name', values.name)
}
>
{() => (
<Form>
<div>
<InputBox
type="text"
id="name"
name="name"
htmlFor="name"
label="Name"
placeholder=""
/>
<button
type="submit"
// ? Not sure using window is the correct way to do this in nextjs
onClick={(event) => window.open('/register', '_blank')}
>
Start KYC
</button>
</div>
</Form>
)}
</Formik>
)
import { Field, Form, Formik } from 'formik'
import { NextPage } from 'next'
import React from 'react'
const Register: NextPage = () => {
let nameInit = ''
React.useEffect(() => {
if (typeof window !== 'undefined') {
console.log('You are on the browser')
// 👉️ can use localStorage here
} else {
console.log('You are on the server')
// 👉️ can't use localStorage
}
nameInit = localStorage.getItem('name') ?? ''
console.log(nameInit)
}, [])
return (
<Formik
initialValues={{
name: nameInit,
}}
onSubmit={async (values) => {
console.log(values)
}}
>
{() => (
<Form className="space-y-8 divide-y divide-gray-200">
<div className="sm:col-span-2">
<label
htmlFor="name"
>
First name
</label>
<Field
type="text"
name="name"
id="name"
autoComplete="given-name"
/>
</div>
<div className="flex justify-end">
<button
type="submit"
>
Submit
</button>
</div>
</Form>
)}
</Formik>
)
}
Inspecting the page I can see that the value is being set and the console.log at the end of the useEffect also returns the expected value. But the form is still not being populated... My guess is the form is rendered before the useEffect is executed? When I just write the code in the function body instead of using useEffect it seems that is being executed on the server where localStorage is not available.
You're closer than you think! It works across tabs, but you might be using <link> or <a> tags to navigate.
If you use the built in next/link, your app won't refresh and useContext will work for you. Your app will also take advantage of Next JS's speed optimisations. Example:
import Link from "next/link"
const Nav = () => (
<Link href="gosomewhere">
<a>I'm a Link</a>
</Link>
)

React form not submitting when using button nested inside Link tag

In my app I have an order form with a button to "complete order" at the bottom. What I want the button to do is submit the form and push the user to the confirmation page where their order will be displayed. Right now I can do one or the other, but can't figure out how to to both.
My form component:
<form onSubmit={onSubmit}>
<label>Name:
<input
type="text"
name="name"
placeholder="Name"
value={values.name}
onChange={onChange}
/>
</label>
<Link to="/confirmation" >
<button>Complete Order</button>
</Link>
</form>
My onSubmit function:
const formSubmit = () => {
const newOrder = {
name: formValues.name.trim(),
}
setOrder(order.concat(newOrder));
setFormValues(initialFormValues);
}
I can tell my formSubmit function submit isn't working because my formValues don't reset after form submission. If I remove the Link tag and just have the button, they do, but then I don't get the redirect to the confirmation page. Any suggestions on what I can do?
If you want to update/reset the form state then navigate to the "/confirmation" path, you can't use a Link and a button/submit the form at the same time.
Remove the Link component and issue an imperative navigation after enqueueing the state updates. Don't forget to prevent the default form action from occurring so the app isn't reloaded.
import { useNavigate } from 'react-router-dom';
...
const navigate = useNavigate();
...
const onSubmit = (e) => {
e.preventDefault();
const newOrder = {
name: formValues.name.trim(),
};
setOrder(order.concat(newOrder));
setFormValues(initialFormValues);
navigate("/confirmation");
}
...
<form onSubmit={onSubmit}>
<label>Name:
<input
type="text"
name="name"
placeholder="Name"
value={values.name}
onChange={onChange}
/>
</label>
<button type="submit">Complete Order</button>
</form>

React - how to target value from a form with onClick

New to react and currently working on a project with a backend.
Everything functions correctly apart from targeting the value of user selection.
basically whenever a user enters a number the setId is saved properly to the const with no problems while using the onChange method.
this method would render my page every change on text.
I am trying to save the Id only when the user clicks the button. however,
event.target.value does not work with onClick.
I tried using event.currentTarget.value and this does not seem to work.
Code:
<form onSubmit={handleSubmit}>
<label>Company ID</label>
<input value={id} onChange={(e) => setId(e.target.value)} type="number" />
{/* <button value={id} type="button" onClick={(e) => setId(e.currentTarget.value)}>Search</button> */}
</form>
Handle Submit:
const handleSubmit = (e) => {
e.preventDefault();
console.log(id)
}
is there a way of doing this with onclick? since I wouldn't like my component to render on every typo and only once a user has clicked the button.
Componenet:
interface GetOneCompanyProps {
company: CompanyModel;
}
interface RouteParam {
id: any;
}
interface CompanyById extends RouteComponentProps<RouteParam> {
}
function GetOneCompany(): JSX.Element {
const [id, setId] = useState('4');
const [company, setCompany] = useState<any>('');
const handleSubmit = (e) => {
e.preventDefault();
console.log(id)
}
async function send() {
try {
const response = await axios.get<CompanyModel>(globals.adminUrls.getOneCompany + id)
store.dispatch(oneCompanyAction(response.data));
console.log(response);
const company = response.data;
setCompany(company)
} catch (err) {
notify.error(err);
}
}
useEffect(() => {
send();
}, [id]);
return (
<div className="getOneCompany">
<h1>hi </h1>
<form onSubmit={handleSubmit}>
<label>Company ID</label>
<input value={id} onChange={(e) => setId(e.target.value)} type="number" />
{/* <button value={id} type="button" onClick={(e) => setId(e.currentTarget.value)}>Search</button> */}
</form>
<div className="top">
</div>
<br/>
Company: {id}
<br/>
Client Type: {company.clientType}
<br/>
Company Name: {company.name}
<br/>
Email Adress: {company.email}
<br/>
</div>
);
}
export default GetOneCompany;
Hope I am clear on this.
Thanks.
You can turn your input from being a controlled input to an uncontrolled input, and make use of the useRef hook. Basically, remove most of your attributes from the input element, and grab the current value of the input form on click of the button. From there, you can do whatever you want with the input value.
const inputRef = useRef()
...other code
<form onSubmit={handleSubmit}>
<label>Company ID</label>
<input type="number" ref={inputRef} />
<button value={id} type="button" onClick={() => console.log(inputRef.current.value)}>Search</button>
</form>
...other code
I'm afraid to say that here onChange is mandatory as we also are interested in the value which we set by setId. onClick can't be used as we can't set the value in the input.
Hope I'm clear.
Thankyou!

React: invoke props in a function

Fairly new to React so please let me know if I'm approaching this wrong.
In short, I want to be able to redirect to the login component after a form has been submitted in the signUp component.
When we click on a signUp or login button it changes the currentPage state to the assigned value. For example if currentPage is currently set to "Login" it will load the Login component and "Sign Up" with the Sign Up component. The components load as they should but when trying to pass in the props in the SignUp component I can't figure out how to invoke the pageSetter function after the form has been submitted.
I could just do the below, which works but I only want to invoke it in the onSubmit function
<form onSubmit={this.props.pageSetter}>
import React from "react";
function Button(props) {
return (
<button id={props.id} value={props.value} onClick={props.onClick}>
{props.value}
</button>
);
}
export default Button;
import SignUp from "./components/signUp.jsx";
import Login from "./components/login.jsx";
class App extends Component {
state = {
currentPage: "Login",
};
pageSetter = ({ target }) => {
this.setState({ currentPage: target.value });
};
render() {
return (
<div>
{this.state.currentPage !== "Sign Up" && (
<Button id={"signUp"} value={"Sign Up"} onClick={this.pageSetter} />
)}
{this.state.currentPage !== "Login" && (
<Button id={"login"} value={"Login"} onClick={this.pageSetter} />
)}
{this.state.currentPage === "Login" && <Login />}
{this.state.currentPage === "Sign Up" && (
<SignUp pageSetter={this.pageSetter} />
)}
</div>
);
}
}
export default App;
class SignUp extends Component {
myChangeHandler = (event) => {
let attribute = event.target.id;
let value = event.target.value;
this.setState({ [attribute]: value });
};
onSubmit = (event) => {
event.preventDefault();
this.props.pageSetter.value = "Login"
this.props.pageSetter
};
render() {
console.log(this.state);
return (
<div>
<form onSubmit={this.onSubmit}>
<p>real_name:</p>
<input id="real_name" type="text" onChange={this.myChangeHandler} />
<p>username:</p>
<input id="username" type="text" onChange={this.myChangeHandler} />
<p>email:</p>
<input id="email" type="text" onChange={this.myChangeHandler} />
<p>password:</p>
<input
id="password"
type="password"
onChange={this.myChangeHandler}
/>
<p>picture</p>
<input id="picture" type="text" onChange={this.myChangeHandler} />
<button id="userSubmit" type="submit">
Submit
</button>
</form>
</div>
);
}
}
export default SignUp;
I think there is a typo in your code example :
onSubmit = (event) => {
event.preventDefault();
this.props.pageSetter.value = "Login"
this.props.pageSetter
};
Could you please edit it and i'll check again if I can help !
Also, despite the typo, I don't understand why you try to set the property "value" on the props pageSetter which is a function.
I couldn't understand either why you're setting a property in a function. Instead of doing this, you should invoke the function using the value as argument.
this.props.pageSetter('Login');
You also should fix the pageSetter function to receive the page value instead of an event.

redux-form: Passing an _id to the submit handler along with formProps

I'm building an edit button for my CRUD app. In this component, each individual 'rating' is mapped into one of these components. The component starts out be displaying the rating as stored in the DB, but users can press the edit button, and it turns into a form! (eventually, I'll get initial values to populate the form fields with the data displayed in the alternate render option).
Right now for the edit button, I have a custom submit handler receiving the submitted data from the two form fields as 'formProps'. However, before passing these off to the backend API, I ALSO need to figure out how to tie an id or something to the submit handler.
As seen in the component right below the form, this whole child component has access to the necessary passed down from the parent which can accessed as 'this.props.id'. Is there anyway to bundle 'this.props.id' with formProps before the handleSubmit takes it all to Redux Actions?
class Rating extends Component{
constructor(props){
super(props);
this.state = {
formClass: "notShowing",
ratingClass: "showing"
}
}
renderForm = () => {
this.state.formClass === "notShowing"
? this.setState({formClass: "showing", ratingClass: "notShowing"})
: this.setState({formClass: "notShowing", ratingClass: "showing"})
}
onSubmit = (formProps) => {
console.log("this is what the submitHandler recieves;", formProps);
this.props.editRating(formProps, () => {
this.props.history.push('/userDashboard');
});
}
render() {
const { handleSubmit, reset } = this.props;
return (
<div className="card darken-1" key={this.props._id}>
<div className={this.state.formClass}>
<form onSubmit={handleSubmit(this.onSubmit)}>
<p>What are you rating?</p>
<fieldset>
<Field
name="title"
type="text"
component="input"
autoComplete="none"
/>
<p>Add your rates!</p>
<Field
name="value"
type="number"
component="input"
autoComplete="none"
/>
</fieldset>
<button onClick={this.renderForm} type="submit" className="teal btn-flat right white-text">Submit</button>
</form>
<button onClick={this.renderForm}>Cancel</button>
</div>
<div className={this.state.ratingClass}>
<div className="card-content">
<span className="card-title">{this.props.title}</span>
<p>{this.props.value}</p>
<button onClick={this.renderForm}>Edit</button>
<button onClick={() => this.props.deleteRating(this.props.id)}>Delete</button>
</div >
</div>
</div>
);
}
}
function mapStateToProps({ratings}) {
return { ratings };
}
export default compose(
connect(mapStateToProps, actions),
reduxForm({ form: 'editRating' })
)(Rating);
You can use the third parameter of the handleSubmit function.
onSubmit = (values, _, props) => {
console.log(values, props.id);
...
}
...
const { handleSubmit, reset } = this.props;
<form onSubmit={handleSubmit(this.onSubmit)} .../>
Reference: https://redux-form.com/7.4.2/docs/api/reduxform.md/#-code-onsubmit-function-code-optional-

Resources