I have a form which is dynamically built using Ionic React and Yup for validation, this is done based on information coming from an API but I have an issue if I do not select a radio button when I press submit the radio buttons become unclickable which means I can never get the error away.
I have created an example here with a hardcoded form rather than it being populated dynamically and if you click Save without doing anything you will then not be able to select the radio buttons but I can't workout where my issue is coming from.
Link to example of my issue
Edit:
Here is the main section of code not working:
import React, { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
import * as yup from "yup";
import { yupResolver } from "#hookform/resolvers/yup";
import {
IonList,
IonRadioGroup,
IonItem,
IonLabel,
IonRadio,
IonButton,
IonContent,
IonPage,
setupIonicReact,
IonInput
} from "#ionic/react";
/* Core CSS required for Ionic components to work properly */
import "#ionic/react/css/core.css";
/* Basic CSS for apps built with Ionic */
import "#ionic/react/css/normalize.css";
import "#ionic/react/css/structure.css";
import "#ionic/react/css/typography.css";
/* Optional CSS utils that can be commented out */
import "#ionic/react/css/padding.css";
import "#ionic/react/css/float-elements.css";
import "#ionic/react/css/text-alignment.css";
import "#ionic/react/css/text-transformation.css";
import "#ionic/react/css/flex-utils.css";
import "#ionic/react/css/display.css";
/* Theme variables */
import "./theme/variables.css";
setupIonicReact();
const validationSchema = yup.object().shape({
q7: yup.string().required("selection is required")
});
export default function App() {
const {
register,
reset,
getValues,
handleSubmit,
control,
formState: { errors }
} = useForm({
resolver: yupResolver(validationSchema),
mode: "all"
});
const onSubmit = (data: any) => {
console.log(data);
};
// useEffect(() => {
// reset({
// // q7: "6"
// });
// }, [reset]);
return (
<React.Fragment>
<IonPage className="xion-page" id="main-cntent">
<IonContent className="ion-padding">
<div className="App">
<form onSubmit={handleSubmit(onSubmit)}>
<>
values:{getValues("name")}
<IonInput {...register("name")}></IonInput>
error:{errors["q7"]?.message}
values:{getValues("q7")}
<Controller
control={control}
name="q7"
render={({ field: { onChange, value, ref } }) => (
<>
{console.log(value)}
<IonList>
<IonRadioGroup
ref={ref}
defaultValue=""
// allowEmptySelection={true}
value={value ?? ""}
onIonChange={({ detail: { value } }) =>
onChange(value ?? "")
}
>
<IonItem>
<IonLabel>Type 2</IonLabel>
<IonRadio value="2" slot="start" />
</IonItem>
<IonItem>
<IonLabel>Type 4</IonLabel>
<IonRadio slot="start" value="4" />
</IonItem>
<IonItem>
<IonLabel>Type 6</IonLabel>
<IonRadio slot="start" value="6" />
</IonItem>
</IonRadioGroup>
</IonList>
</>
)}
/>
<br />
<IonButton type="submit">Save</IonButton>
</>
</form>
</div>
</IonContent>
</IonPage>
</React.Fragment>
);
}
Your problem is that you should pass in onChange function js event.
In onIonChange modified event with custom properties.
But you actually passed a value to the function, not an event.
You can find in docks where is standard js event in onIonChange or just setValue
<IonRadioGroup
{...field}
onIonChange={
(event) => {
setValue('q7', event.detail.value)
}
}
>
https://codesandbox.io/s/crimson-breeze-d9fptl?file=/src/App.tsx:2253-2591
Related
I'm working on a React typescript project and need to create a dropdown with the necessary name and link to navigate as props, which will be displayed as menu items in my dropdown. But when I defined values in the same dropdown.tsx file, the onChange event worked properly. But when I received values as props, the onChange event won't work.
Here is my DropdownComponent.tsx file
import * as React from 'react';
import OutlinedInput from '#mui/material/OutlinedInput';
import MenuItem from '#mui/material/MenuItem';
import Select, { SelectChangeEvent } from '#mui/material/Select';
import SearchOutlinedIcon from '#mui/icons-material/SearchOutlined';
import { Box, Button, InputBase } from '#mui/material';
// React-Router Imports
import { Link as RouterLink } from 'react-router-dom/';
/* eslint-disable-next-line */
export interface DropdownComponentProps {
dashboardnames: Array<{
name: string,
link: string
}>,
renderDashboard:()=>void
}
export function DropdownComponent(props: DropdownComponentProps) {
const [configName, setConfigName] = React.useState<string>();
const handleChange = (event: SelectChangeEvent<typeof configName>) => {
const {
target: { value },
} = event;
setConfigName(value);
};
return (
<Box sx={{ marginTop:-5}}>
<Select
sx={{width:190,height:36}}
displayEmpty
value={configName}
onChange={handleChange}
input={<OutlinedInput />}
renderValue={(selected) => {
if (!selected) {
return <>Mushroom tunnel 1</>;
}
return selected;
}}
inputProps={{ 'aria-label': 'Without label' }}
>
<MenuItem disabled value="">
Frequently visited
</MenuItem>
<div style={{marginLeft:'20px', display:'flex'}}> <InputBase placeholder='search'/>
<div style={{marginLeft:'10px', marginRight:'10px'}}>
<Button><SearchOutlinedIcon /></Button>
</div>
</div>
{props.dashboardnames.map((page) => (
<MenuItem
component={RouterLink}
to={page.link}
key={page.name}
onClick={props.renderDashboard}
>
{page.name}
</MenuItem>
))}
</Select>
</Box>
);
}
export default DropdownComponent;
What's the mistake I've made here? Can someone help me with this issue? Thank you in advance!
import React, { useState } from "react";
import TextField from "#mui/material/TextField";
import {} from "#fortawesome/free-solid-svg-icons";
import { Box, Chip, Grid, Typography } from "#mui/material";
import VoiceRecognice from "../component/VoiceRecognice";
import SpeechRecognition, {
useSpeechRecognition,
} from "react-speech-recognition";
import IconButton from "#mui/material/IconButton";
import MicIcon from "#mui/icons-material/Mic";
const addDream = () => {
const [story, setStory] = useState("");
console.log(story);
const {
transcript,
listening,
resetTranscript,
browserSupportsSpeechRecognition,
} = useSpeechRecognition();
if (!browserSupportsSpeechRecognition) {
return <span>Browser doesn't support speech recognition.</span>;
}
};
return (
<>
<Grid item xs={11}>
<TextField
label="Dream story"
multiline
rows={5}
fullWidth
value={transcript}
onChange={(e) => setStory(e.target.value)}
/>
</Grid>
<Grid item xs={1}>
<p>{listening ? "Mic On" : "Mic Off"}</p>
<IconButton color="primary" onClick{SpeechRecognition.startListening}>
<MicIcon />
</IconButton>
</Grid>
</>
);
export default AddDream;
I want to set browser support speech recognition value to TextField value. I want to edit that speech recognition value. In my code, didn't edit value and didn't get the input value. But transcript value is displayed in TextField.
You can use a useEffect hook to update story state with transcript value:
useEffect(() => {
setStory(transcript);
}, [transcript]);
And then in the TextField:
<TextField
label="Dream story"
multiline
rows={5}
fullWidth
value={story}
onChange={(e) => setStory(e.target.value)}
/>
I'm new to React and still am trying to make sense of a few things. I'm using the react-form-dom library and after looking into the documentation I can't figure out what's going on with my project.
I have created a custom input component that takes in a few parameters. The problem is that when I try to log the value of the inputs I get undefined.
Input.jsx
import React, { useState } from 'react';
import './Input.scss';
export default function Input(props, {register, errors}) {
const [inputVal, setInputVal] = useState('');
const nameChange = (e) => {
setInputVal(e.target.value);
props.nameChange(e.target.value);
}
const legend = <span className='legend'>{props?.legend}</span>;
const showLength = <span className='legend'>{props.maxLength - inputVal.length}</span>;
return (
<div className="input-holder">
<input
ref={register}
type={props.type || 'text'}
id={props.id}
placeholder={props.placeholder}
value={inputVal}
onInput={nameChange}
maxLength={props.maxLength || ""}
/>
{ props.legend ? legend : null}
{ props.showLength && props.maxLength ? showLength : null }
</div>
)
}
Form.jsx
import React from 'react';
import { useForm } from "react-hook-form";
import Button from './Button';
import Input from './Input';
export default function UserForm(props) {
const { register, handleSubmit } = useForm();
function submitForm(data) {
console.log(data)
}
return (
<div className="user-form">
<form onSubmit={handleSubmit(submitForm)}>
<Input
placeholder="Name"
nameChange={(name) => props.userName(name)}
showLength="true"
maxLength="35"
legend="Remaining Char: "
id="name"
register={register}
/>
<Input
placeholder="E-mail"
type="email"
id="email"
register={register}
/>
<Button label="Buy" />
</form>
</div>
)
}
It seems that you are using react-hook-form
Checkout the example here
The onChange you are passing to the input tags are no longer needed with react-hook-form beacuse of register functionality of react-hook-form
also validations will be done react-hook-form
import React from 'react';
import { useForm } from "react-hook-form";
export default function UserForm(props) {
const { register, handleSubmit } = useForm();
const submitForm = (data) => {
console.log(data);
}
const onError = (err) => {
console.error(err);
}
return (
<div className="user-form">
<form onSubmit={handleSubmit(submitForm, onError)}>
<input
{...register("name", { //handles onChange, value, name, ref
maxLength: 35 // Your validations
})}
/>
<button>Buy</button>
</form>
</div>
)
}
Checkout docs for register
Form File Example
I am trying to use ChakraUI and React-Hook-Form to create my form. However, my errors are not working. I have tried not using chakra ui but still it does not work. Here is my code:
import React from 'react'
import { useForm } from "react-hook-form";
import "./App.css"
import { Input } from "#chakra-ui/react"
import { Text } from "#chakra-ui/react"
import {
Alert,
AlertIcon,
AlertTitle,
AlertDescription,
} from "#chakra-ui/react"
function App() {
const { register, handleSubmit, errors } = useForm();
const onSubmit = data => console.log(data);
return (
<div className="app-container">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="header-container">
<Text fontSize="3xl" align="center" className="app-header">Finish the survey</Text>
</div>
<div className="email">
<Text fontSize="xl">Your Email</Text>
<Input name="email" placeholder="Your Email..." type="text" ref={register({ maxLength: { value: 23, message: "test" } })} />
{errors.email && (<span>{errors.email.message}</span>)}
</div>
</form>
</div>
)
}
export default App
Without knowing the version of the library you are using, I can't say for certain, but try changing
const { register, handleSubmit, errors } = useForm();
to
const { register, handleSubmit, formState: { errors } } = useForm();
I ran into the same problem when following their example off of the home page of the library's website and have since put in a PR.
I've created a login form and accessing states through a context api. Can't seem to find a problem in my code but these errors are showing up:
Errors: 1-Legacy context API has been detected within a strict-mode tree...
2-findDOMNode is deprecated in StrictMode. findDOMNode was passed an instance of Transition which
is inside StrictMode. Instead, add a ref directly to the element you want to reference.
Code:
import React,{useContext, useState, useEffect} from 'react'
import {auth} from '../firebase/firebase';
const AuthContext= React.createContext();
export function useAuth(){
return useContext(AuthContext);
}
export function AuthProvider({children}) {
const[currentUser,setCurrentUser]= useState();
function login(email, password){
return auth.signInWithEmailAndPassword(email, password)
}
useEffect(()=>{
const unsubscriber= auth.onAuthStateChanged(user=>{
setCurrentUser(user)
})
return unsubscriber
},[])
const value={
currentUser,
login
}
return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
)
}
// Login form//
import React, {useRef, useState} from 'react';
import './login.css';
import {Button, Form, FormGroup, Input, Label} from 'reactstrap';
import {useAuth} from '../../context/AuthContext'
import { Alert } from 'reactstrap';
const Login=()=> {
const emailRef = useRef();
const passwordRef=useRef();
const {login} = useAuth();
const[error,setError]=useState();
async function handlesubmit(e){
e.preventDefault()
try{
setError('')
await login(emailRef.current.value,passwordRef.current.value)
}
catch{
setError("Failed to Login")
}
}
return (
<div>
<Form className='login-form' onSubmit={handlesubmit}>
{error && <Alert color="danger">{error}</Alert>}
<h1 className='website'><span className='font-weight-bold'>ApniShop</span>.com</h1>
<FormGroup>
<label>Email</label>
<Input name='email' type='text' placeholder='Email' ref={emailRef}/>
</FormGroup>
<FormGroup>
<label>Password</label>
<Input name='password' type='password' placeholder='password' ref={passwordRef}/>
</FormGroup>
<Button className='btn-lg btn-block' outline color ="danger" type='submit'>Log in</Button>
</Form>
</div>
)
}
export default Login;