On submits doesn't trigger a function in ReactJs - reactjs

const CreateMessage = () => {
const disatch = useDispatch()
const chatR = useSelector(state => state.chat);
const { chat } = chatR;
const [text, setText] = useState("")
useEffect(()=>{
setText("")
},[chat])
function handleSubmit(event) {
event.preventDefault()
console.log(3333)
}
return (
<StyledCreateMessage id="myform" onSubmit={handleSubmit}>
<div className="searchForm">
{/* <input className='input' type="text" placeholder='Write a message...' /> */}
<textarea value={text} onChange={(e)=>setText(e.target.value)} spellCheck="false" className='input' placeholder='write a message...'></textarea>
</div>
<div className="send">
<Stack direction="row" spacing={1}>
<IconButton color="primary" sx={{color:"white"}} aria-label="upload picture" component="label">
<input hidden type="file" />
<AttachFileIcon />
</IconButton>
<IconButton color="primary" sx={{color:"white"}} aria-label="upload picture" component="label">
<input hidden type="file" accept='image/*' />
<PhotoCamera />
</IconButton>
<IconButton type="submit" form="myform" color="primary" sx={{color:"white"}} aria-label="upload picture" component="label">
<SendIcon />
</IconButton>
</Stack>
</div>
</StyledCreateMessage>
)
}
why when I clock
<IconButton type="submit" form="myform" color="primary" sx={{color:"white"}} aria-label="upload picture" component="label">
<SendIcon />
</IconButton>
It doesn't trigger handleSubmit

You need to add onClick={handleSubmit} to your IconButton.
Here is an example right from react docs: https://reactjs.org/docs/forms.html

Your form won't have the context of the button based on the way you have it set up.
There are a few things you can do
The button would have to be in the form itself, which seems like what you'd want.
Do the onClick solution mentioned above
Pass some state between the form component and the button, which seems difficult for something simple.

Related

why does handleSubmit in react hook useform is not being called

I am using useform hook but the handlesubmit function is not being called . here is the code:
This is the useform hook i am using
const {
register,
handleSubmit,
formState: { errors },
watch,
reset, } = useForm<SellingInvoiceClientDetails>({
resolver: yupResolver(SellingInvoiceScheme),
defaultValues: {
rib: "",
cardNumber: "",
cardType: CardType.IDENTITY_CARD,},});
The function i want to call in the hundleSubmit is the following
const addSellingInvoiceClientDetails = (
sellingInvoiceDetails: SellingInvoiceClientDetails
) => {
console.log(sellingInvoiceDetails.cardType);
props.setSelectedClient();
props.updateSellingInvoiceInfo(
sellingInvoiceDetails.cardType,
sellingInvoiceDetails.cardNumber,
sellingInvoiceDetails.rib
);
handleClose(); };
The code of the Form :
return (
<>
<Modal.Header closeButton>
<Modal.Title>
<FormattedMessage id={"client.info"} />
</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form onSubmit={handleSubmit(addSellingInvoiceClientDetails)}>
<Form.Group className="mb-3">
<Form.Label>
<FormattedMessage id={"card.number"} />
</Form.Label>
<Form.Control
{...register("cardNumber")}
placeholder={intl.formatMessage({ id: "card.number" })}
/>
<Form.Text className=" text-danger">
{errors.cardNumber?.message}
</Form.Text>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>
<FormattedMessage id={"card.type"} />
</Form.Label>
<Form.Check
{...register("cardType")}
type={"radio"}
label={intl.formatMessage({ id: CardType.IDENTITY_CARD })}
value={CardType.IDENTITY_CARD}
id={"identity_card"}
/>
<Form.Check
{...register("cardType")}
type={"radio"}
label={intl.formatMessage({ id: CardType.DRIVING_LICENCE })}
value={CardType.DRIVING_LICENCE}
id={"driving_licence"}
/>
<Form.Text className=" text-danger">
{errors.cardType?.message}
</Form.Text>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>RIP</Form.Label>
<input
type="text"
className="form-control"
{...register("rib")}
placeholder="XXXXXXXXXXXXX"
/>
<Form.Text className=" text-danger">
{errors.rib?.message}
</Form.Text>
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
<FormattedMessage id={"cancel"} />
</Button>
<Button
type="submit"
variant="primary"
onClick={handleSubmit(addSellingInvoiceClientDetails)}
>
<FormattedMessage id={"ok"} />
</Button>
</Modal.Footer>
</>
);
the function addSellingInvoiceClientDetails is not being excuted and when i click the Ok button nothing happens altough the handleClose function called in cancel button is working just fine.
You have put the Button element out of the form.
Try to move it inside the <form> tag

Using useRef to assign focus to an element that conditionally exists

I am having some trouble trying to implement this functionality which creates an input field component upon clicking a button, and then assigning focus to the input field as well. I am getting an error saying that inputRef.current is undefined, and am not sure how to proceed.
export default function Post(props) {
const inputRef = React.useRef();
const [commentsToggle, setCommentsToggle] = React.useState(false);
function commentClickHandler() {
setCommentsToggle((prev) => !prev);
inputRef.current.focus();
}
return (
<div className="post">
<div className="postAuthor">
<Avatar
{...stringAvatar(`${props.post.author.username}`)}
alt={`${props.post.author.username}'s Avatar`}
src="./placeholder.jpg"
variant="rounded"
style={avatarStyle}
>
{props.post.author.username[0].toUpperCase()}
</Avatar>
<b>{props.post.author.username}</b> posted:
</div>
<p className="postContent">{props.post.content}</p>
<p className="postDate">{props.post.formatted_date}</p>
<span className="postButtonContainer">
<IconButton className="starsButton" onClick={starClickHandler}>
{props.post.stars.includes(userInfo.userID) ? (
<StarIcon />
) : (
<StarBorderIcon />
)}
{props.post.stars.length}
</IconButton>
<Tooltip title="Add a comment." placement="right">
<IconButton className="commentsButton" onClick={commentClickHandler}>
{commentsToggle ? <ChatBubbleIcon /> : <ChatBubbleOutlineIcon />}
{props.post.comments.length}
</IconButton>
</Tooltip>
</span>
<hr></hr>
<div>
<CommentList comments={props.post.comments}></CommentList>
{commentsToggle ? (
<NewCommentInput
ref={inputRef}
targetPostURL={props.post.url}
getUserData={props.getUserData}
setCommentsToggle={setCommentsToggle}
></NewCommentInput>
) : null}
</div>
</div>
);
}
The above is the code from my parent component, which will conditionally render the child component (the input) that I want to receive focus. Below is this input component:
const NewCommentInput = React.forwardRef((props, ref) => {
return (
<form className="commentInput" onSubmit={commentSubmitHandler}>
<TextField
ref={ref}
multiline
fullWidth
size="small"
name="comment"
placeholder="comment on this post..."
value={commentState.content}
onChange={commentChangeHandler}
></TextField>
<Button variant="outlined" onClick={commentSubmitHandler}>
Comment
</Button>
</form>
);
});
How can I solve inputRef.current being undefined when I click the button that create the component that has the ref?

What is the flow of control?

I am not understanding the flow of control since I am a newbie. In this code, after the component is rendered, useEffects get called. When the first useEffect is called, it is dispatching an action. So, after the action is dispatched, it should re-render the component because I am fetching the change in state from useSelector. Instead, it is executing the second useEffect. Similar is the case with the third useEffect, after it is triggered, it is changing the formData which is in useState. Instead of re-rendering, it is executing the 4th useEffect. Can anyone please help me understand the flow right from the start to the end?
import React,{useState,useEffect,useRef} from "react";
import AdminLayout from "../../../hoc/adminLayout";
import {useFormik,FieldArray,FormikProvider} from "formik";
import {useDispatch,useSelector} from "react-redux";
import {validation,formValues} from "./validationSchema";
import {getAdminArticle,updateArticle} from "../../../store/actions/articles_actions";
import {clearCurrentArticle} from "../../../store/actions/index";
import Loader from "../../../utils/loader";
import {
TextField,
Button,
Divider,
Chip,
Paper,
InputBase,
IconButton,
Select,
MenuItem,
FormControl,
FormHelperText
} from '#material-ui/core';
import AddIcon from '#material-ui/icons/Add';
import WYSIWYG from "../../../utils/forms/wysiwyg";
const EditArticle=(props)=>{
const dispatch=useDispatch();
const notifications=useSelector((state)=>{
return state.notifications;
})
const articles=useSelector((state)=>{
return state.articles;
})
const [isLoading, setIsLoading]=useState(true);
const [editorBlur,setEditorBlur]=useState(false);
const [formData,setFormData]=useState(formValues);
const actorsValue=useRef("");
/////edit/////
const [editContent,setEditContent]=useState(null);
////edit////
const formik=useFormik({
enableReinitialize:true,
initialValues:formData,
validationSchema:validation,
onSubmit:(values,{resetForm})=>{
//console.log(values);
setIsLoading(true);
dispatch(updateArticle(values,props.match.params.id));
}
});
const handleEditorState=(state)=>{
formik.setFieldValue("content",state,true);
}
const handleEditorBlur=(blur)=>{
setEditorBlur(true);
}
const errorHelper=(formik,value)=>{
return {
error:formik.errors[value] && formik.touched[value]? true:false,
helperText:formik.errors[value] && formik.touched[value]?formik.errors[value]:null
}
}
///////edit/////////
useEffect(()=>{
console.log("first");
dispatch(getAdminArticle(props.match.params.id));
},[dispatch,props.match.params])
/////edit///////
useEffect(()=>{
console.log("second");
// if(notifications && notifications.success){
// props.history.push("/dashboard/articles");
// }
// if(notifications && notifications.error){
setIsLoading(false);
// }
},[notifications,props.history])
useEffect(()=>{
console.log("third");
if(articles && articles.current){
setFormData(articles.current);
setEditContent(articles.current.content);
}
},[articles])
useEffect(()=>{
console.log("unmounted");
return ()=>{
dispatch(clearCurrentArticle());
}
},[dispatch])
return <AdminLayout section="Add Article">
{console.log("rendered")}
{isLoading?<Loader />:<form className="mt-3 article_form" onSubmit={formik.handleSubmit}>
<div className="form-group">
<TextField
style={{width:"100%"}}
name="title"
label="Enter a title"
variant="outlined"
{...formik.getFieldProps("title")}
{...errorHelper(formik,"title")}
/>
</div>
<div className="form-group">
<WYSIWYG setEditorState={(state)=>{
return handleEditorState(state)
}} setEditorBlur={(blur)=>{
return handleEditorBlur(blur)
}}
editContent={editContent}
/>
{formik.errors.content && editorBlur?
<FormHelperText error={true}>
{formik.errors.content}
</FormHelperText> :null}
<TextField
type="hidden"
name="content"
{...formik.getFieldProps("content")}
/>
</div>
<div className="form-group">
<TextField
style={{width:"100%"}}
name="excerpt"
label="Enter an excerpt"
variant="outlined"
{...formik.getFieldProps("excerpt")}
{...errorHelper(formik,"excerpt")}
multiline
rows={4}
/>
</div>
<Divider className="mt-3 mb-3" />
<h5>Movie Data and Score</h5>
<div className="form-group">
<TextField
style={{width:"100%"}}
name="score"
label="Enter an score"
variant="outlined"
{...formik.getFieldProps("score")}
{...errorHelper(formik,"score")}
/>
</div>
<FormikProvider value={formik}>
<h5>Add the Actors</h5>
<FieldArray name="actors"
render={
arrayhelpers=>(
<div>
<Paper className="actors_form">
<InputBase
className="input"
placeholder="Add actor name here"
inputRef={actorsValue}
/>
<IconButton onClick={()=>{
arrayhelpers.push(actorsValue.current.value);
actorsValue.current.value="";
}}>
<AddIcon />
</IconButton>
</Paper>
{formik.errors.actors && formik.touched.actors?
<FormHelperText error={true}>
{formik.errors.actors}
</FormHelperText> :null}
<div className="chip_container">
{formik.values.actors.map((actor,index)=>{
return <div key={actor}>
<Chip label={`${actor}`} color="primary" onDelete={()=>{
return arrayhelpers.remove(index);
}}>
</Chip>
</div>
})}
</div>
</div>
)
}
/>
</FormikProvider>
<div className="form-group">
<TextField
style={{width:"100%"}}
name="score"
label="Enter the Director"
variant="outlined"
{...formik.getFieldProps("director")}
{...errorHelper(formik,"director")}
/>
</div>
<FormControl variant="outlined" >
<h5>Select a Status</h5>
<Select
name="status"
{...formik.getFieldProps("status")}
error={formik.errors.status && formik.touched.status? true:false}
>
<MenuItem value=""><em>None</em></MenuItem>
<MenuItem value="draft">Draft</MenuItem>
<MenuItem value="public">Public</MenuItem>
</Select>
{formik.errors.status && formik.touched.status?
<FormHelperText error={true}>
{formik.errors.status}
</FormHelperText> :null}
</FormControl>
<Divider className="mt-3 mb-3" />
<Button variant="contained" color="primary" type="submit" >
Edit Article
</Button>
</form>
}
</AdminLayout>
}
export default EditArticle;
[enter image description here][1]

Why button's onClick event is triggered when i typing in TextField ReactJS

I have a sample code for Signing page as follows, When I am typing the username and passwords inside the text fields with every character the onClick event of the button is triggered and I can see the output of console.log(). Why it is triggered?
class Signin extends React.Component {
state = {
username: null,
password: null,
}
render () {
const { t, classes } = this.props;
return (
<div >
<div >
<div >
<Card>
<CardContent>
<form>
<TextField
inputProps={{ style:{fontSize:20, textAlign:'center', direction:'ltr'} }}
value={this.state.username}
onChange={e => this.setState({username: e.target.value})}
id="username"
label={t("Username")}
className={classes.textField}
fullWidth
margin="normal"
/>
<TextField
inputProps={{ style:{fontSize:20, textAlign:'center', direction:'ltr'} }}
value={this.state.password}
onChange={e => this.setState({password: e.target.value})}
id="password"
label={t("Password")}
className={classes.textField}
type="password"
fullWidth
margin="normal"
/>
<Button variant="raised" color="primary" fullWidth type="submit" onClick={console.log(this.state.username,this.state.password)} >{t("Login")}</Button>
</form>
</CardContent>
</Card>
</div>
</div>
</div>
);
}
}
Change your console.log from:
onClick={console.log(this.state.username,this.state.password)}
to like this below:
onClick={() => console.log(this.state.username,this.state.password)}
try this
it is happening because It depends on where exactly are you using the Arrow function. If the Arrow function is used in the render method, then they create a new instance every time render is called just like how bind would work.
<Button
variant="raised"
color="primary"
fullWidth type="submit"
onClick={()=>{console.log(this.state.username,this.state.password)} >{t("Login")}}</Button>

how to edit a form in react using formik

var fname,
gender,
city = "";
this.props.data.map((row, index) => {
// console.log(index);
if (this.props.selectedVal === index) {
gender = row[0];
fname = row[1];
city = row[2];
}
return [];
});
return (
<div>
<Dialog
open={this.props.open}
onClose={this.handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<h1>Edit User</h1>
<DialogContent>
<DialogContentText id="alert-dialog-description" />
<form onSubmit={handleSubmit}>
<TextField
type="text"
margin="dense"
id="firstname"
label="Name"
onChange={handleChange}
value={fname}
{...props}
/>
<br />
<TextField
type="text"
margin="dense"
id="gender"
label="gender"
onChange={handleChange}
value={gender}
{...props}
/>
<br />
<TextField
type="text"
margin="dense"
id="city"
label="city"
onChange={handleChange}
value={city}
{...props}
/>
</form>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
RESET
</Button>
<Button onClick={this.handleClose} color="primary" autoFocus>
SUBMIT
</Button>
</DialogActions>
</Dialog>
</div>
);
};
render() {
return (
<div align="center">
<Formik
initialValues={{
name: this.props.fname,
gender: this.props.gender,
city: this.props.city
}}
onSubmit={initialValues => console.log("values" + initialValues.name)}
render={this.form}
/>
</div>
);
}
}
Here i am getting the values from table while click on a specific row. I'm getting these values in a dialog using formik. Now i want to edit this formik form. I faced a problem. These values are not edited. How to edit these readonly values.
I added my codesandbox link codesandbox
The way you are doing things is not correct. Some of the functions which you are using never exist.
Here is the working demo of your code Codesandbox demo
Please take a look at the code and understand how it is transformed between two components and feel free to ask me if you have any queries/get stuck understanding the code.

Resources