my onclick function overlapped with submit handler - reactjs

when i put onClick event the form does not validate and if i delete onClick event the form does not want to submit
so recently i just start a new project with kendo react. on this project i tried to create customize grid where i can add new lines, edit or remove.
<form style={{ width: '1000px' }} onSubmit={this.handleSubmit} >
<div className="col-lg-3 col-md-3 col-sm-3 col-xs-3">
<div className="k-animation-container">
<DropDownList
defaultValue={this.state.productInEdit.Programto || ''}
onChange={this.onDialogInputChange}
name="Programto"
required={true}
data={this.prog}
/>
</div>
</div>
</div>
<div className="row" >
<DialogActionsBar>
<Button
className="k-button"
onClick={this.props.cancel}
>
Cancel
</Button>
<Button className="mt-3" type="submit" primary={true} onClick={this.props.save} > Save </Button>
</DialogActionsBar>
</div>
</form>
and this is the event for validation
handleSubmit = (event) => {
event.preventDefault();
this.setState({ success: true });
setTimeout(() => { this.setState({ success: false }); }, 3000);
}
and submit code i create it on different page, so i need to call the event with this.props.save;
save = () => {
const dataItem = this.state.productInEdit;
const products = this.state.products.slice();
if (dataItem.ProductID === undefined) {
products.unshift(this.newProduct(dataItem));
} else {
const index = products.findIndex(p => p.ProductID === dataItem.ProductID);
products.splice(index, 1, dataItem);
}
this.setState({
products: products,
productInEdit: undefined
});
}
i tried to call save event inside the handleSubmit but still not working

Related

How do I send data to my backend by clicking on save the page with REACT

How is it possible to send these data (Taste, Trust, content of question all questions (which are in Tabs.jsx), everything except the description see the picture please) to my backend by clicking on 'Save the page'.In first part before putting any url inside, I really want to see the data in the console log for now I have nothing printed out except this message :
SyntheticBaseEvent {_reactName: "onClick", _targetInst: null, type: "click", nativeEvent: PointerEvent, target: HTMLButtonElement…}
I have 2 versions but I don't know the difference, what is better to use, I just saw these 2 ways in this forum.
export default function MenuItemDisplay() {
const [data, setData] = useState({
taste: "",
trust: ""
});
function onSubmit(e) {
e.preventDefault();
axios
.post("", {
trust: data.trust,
taste: data.taste
})
.then((res) => {
console.log(res.data);
});
}
function handleSubmit(e) {
const newData = { ...data };
newData[e.target.id] = e.target.value;
setData(newData);
console.log(e);
}
const onError = () => {
console.log("Error");
};
function Checkbox({ value }) {
const [checked, setChecked] = useState(true);
return (
<label>
<input
type="checkbox"
defaultChecked={checked}
onChange={() => setChecked(!checked)}
/>
{value}
</label>
);
}
return (
<>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown ... /> .
</div>
...
<Checkbox value={!!item.trust} />
</div>
...
<button
type="submit"
onClick= {handleSubmit}
> Save the content
</button>
</>
);
}
OR the same code with fetch :
export default function MenuItemDisplay() {
const [trust, setTrust] = useState("item.trust");
const [taste, setTaste] = useState("item.taste");
const [message, setMessage] = useState("");
let handle = async (e) => {
e.preventDefault();
try {
let res = await fetch("", {
method: "POST",
body: JSON.stringify({
trust: trust,
taste: taste
})
});
let resJson = await res.json();
if (res.status === 200) {
setTaste("");
setTrust("");
message("Success");
} else {
setMessage("Some error occured");
}
} catch (err) {
console.log(err);
}
};
return (
<>
<form onSubmit={hadle}>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown
style={styles.select}
options={TASTE}
defaultValue={TASTE.find((t) => t.label === item.taste)}
styleSelect={colourStyles}
isMulti={true}
/>
</div>
<div className="TextStyle">
{"Trust "}
<Checkbox value={!!item.trust} />
</div>
<div className="TextStyle"> Description : {item.description} </div>
<Tabs data={item.questions} />
</div>
<button>Save</button>
</form>
</>
);
}
Plus I have another form inside my MenuItemDisplay component that is Tabs.jsx. I really don't don't how can I deal with these 2 forms and how to 'trace' these data...
Here is my code
You can go with the following approaches.
Using a form element
You need to send the form data to the backend using AJAX calls. The most conventional way to do so is to use a JSX form element.
export default function MenuItemDisplay() {
...
return (
<form onSubmit={handleSubmit}>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown
style={styles.select}
options={TASTE}
defaultValue={TASTE.find((t) => t.label === item.taste)}
styleSelect={colourStyles}
isMulti={true}
/>
</div>
<div className="TextStyle">
{"Trust "}
<Checkbox value={!!item.trust} />
</div>
<div className="TextStyle"> Description : {item.description} </div>
<Tabs data={item.questions} />
</div>
<button type="submit"> Save the page</button>
</form>
);
}
Using a handleSubmit callback to the save button
Another way to do it using the button to send the request to the backend when clicked.
export default function MenuItemDisplay() {
...
return (
<>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown
style={styles.select}
options={TASTE}
defaultValue={TASTE.find((t) => t.label === item.taste)}
styleSelect={colourStyles}
isMulti={true}
/>
</div>
<div className="TextStyle">
{"Trust "}
<Checkbox value={!!item.trust} />
</div>
<div className="TextStyle"> Description : {item.description} </div>
<Tabs data={item.questions} />
</div>
<button onClick={handleSubmit}> Save the page</button>
</>
);
}
All you need to do is define the handleSubmit callback. If you use the form element, you'd need to prevent the default form submission behavior.
async function handleSubmit(e) {
e.preventDefault(); // if you use the form tag
// validate the data here
// use fetch or axios or any other 3rd party library to send data to the back end
// receive response from backend
// do something with the response
}

How to fix "cannot update during an existing state transition (such as within `render`)" problem?

I get this problem even though my code doesn't update the state directly.
Here's my code:
export class Login extends React.Component {
static contextType = getContext();
_usernameValue = "";
_passwordValue = "";
// adding value to notification variable activates notification
state = { mode: "signin", notification: "" };
constructor(props) {
super(props);
this.showNotificationDeb = debounceOnce(this.showNotification, 200);
this.closeNotificationDeb = debounceOnce(this.closeNotification, 200);
}
signinClicked = () => {
this.context.dispatch({
type: "LOGIN",
payload: {
username: this._usernameValue,
password: this._passwordValue,
callback: this.incorrectCredentials,
},
});
};
forgotPasswordClicked = () => {
this.setState({ mode: "password" });
};
sendPasswordRequest = () => {
this.context.dispatch({
type: "FORGOT_PASSWORD",
payload: {
username: this._usernameValue,
password: this._passwordValue,
callback: this.passwordRequestSent,
},
});
};
incorrectCredentials = (errorMessage) => {
this.showNotificationDeb(errorMessage);
};
passwordRequestSent = (message) => {
this.showNotificationDeb(message);
};
restoreSigninWindow = () => {
this.setState({ mode: "signin" });
};
showNotification = (message) => {
console.log("aa");
this.setState({ notification: message });
};
closeNotification = () => {
if (this.state.notification) this.setState({ notification: "" });
};
render() {
return (
<div className={styles.container}>
<div className={styles.loginContainer}>
<Icon
rotate={90}
path={mdiCog}
size={2}
color="black"
className={styles.loginIcon}
/>
<p className={styles.loginTitle}>Sign in to RAS</p>
<div
className={`${styles.notificationContainer} ${
this.state.notification ? "" : styles.hideNotification
}`}
>
<p className={styles.notificationMessage}>
{this.state.notification}
</p>
<p
className={styles.notificationCloseButton}
onClick={() => this.closeNotification()}
>
x
</p>
</div>
<div className={styles.loginWindow}>
{this.state.mode === "signin" ? (
<React.Fragment>
<label className={styles.inputLabel}>Username</label>
<input
id="usernameInput"
className={styles.input}
onChange={(event) => {
this._usernameValue = event.target.value;
}}
></input>
<div className={styles.passwordLabelContainer}>
<label className={styles.inputLabel}>Password</label>
<p
className={styles.forgotPasswordLabel}
onClick={() => this.forgotPasswordClicked()}
>
Forgot password?
</p>
</div>
<input
id="passwordInput"
type="password"
className={styles.input}
onChange={(event) => {
this._passwordValue = event.target.value;
}}
></input>
<Button
variant="contained"
className={styles.button}
onClick={() => this.signinClicked()}
>
Sign in
</Button>
</React.Fragment>
) : (
<React.Fragment>
<div className={styles.backButtonContainer}>
<div onClick={() => this.restoreSigninWindow()}>
<Icon
path={mdiKeyboardBackspace}
size={0.85}
color="black"
className={styles.backIcon}
/>
<p>Back</p>
</div>
</div>
<label className={`${styles.inputLabel}`}>
Enter your email address. Password reset link will be send to
your email address.
</label>
<input
id="usernameInput"
className={styles.input}
placeholder="Enter your email address"
></input>
<Button
variant="contained"
className={styles.button}
onClick={() => this.sendPasswordRequest()}
>
Send
</Button>
</React.Fragment>
)}
</div>
</div>
</div>
);
}
}
As you see, I don't change the state directly. I do it always by calling the functions above. However, according to the React I am changing the state from inside render() function.
I do use lambda functions but I still see the problem.

Using Form Inside Antd Modal

ERRORCODE:
index.js:1 Warning: Instance created by `useForm` is not connected to any Form element. Forget to pass `form` prop?
I am using React with Antd and I open a modal on a button click, the button passes some data which I am capturing via "e" and render them onto the modal.
The problem is whenever the modal is closed and opened again, the contents inside do not re render, it uses the previous event data. I've figured it is because I am not using the Form properly.
I will post the code below please let me know where I have gone wrong.
import react, antd ...etc
function App () => {
const sendeventdata(e) => {
const EventContent = () => (
<div>
<Form
form={form}
labelAlign="left"
layout="vertical"
initialValues={{
datePicker: moment(event.start),
timeRangePicker: [moment(event.start), moment(event.end)],
}}
>
<Form.Item name="datePicker" label={l.availability.date}>
<DatePicker className="w-100" format={preferredDateFormat} onChange={setValueDate} />
</Form.Item>
<Form.Item name="timeRangePicker" label={l.availability.StartToEnd}>
<TimePicker.RangePicker className="w-100" format="HH:mm" />
</Form.Item>
<span className="d-flex justify-content-end">
<Button
className="ml-1 mr-1"
onClick={() => {
form
.validateFields()
.then((values) => {
onUpdate(values)
form.resetFields()
})
.catch((info) => {
console.log('Validate Failed:', info)
})
}}
>
{l.availability.updateBtn}
</Button>
<Button danger className="ml-1 mr-1" onClick={() => handleDelete()}>
Delete
</Button>
</span>
</Form>
</div>
)
}
const MyModal = () => {
const { title, visible, content } = e
return (
<Modal
onCancel={handleModalClose}
title={title}
visible={visible}
footer={null}
form={form}
destroyOnClose
>
{content}
</Modal>
)
}
return <div><MyModal /><Button onClick{sendeventdata}></Button></div>
}

my form not submitting so where is the problem

as you see my form not submit i can't see where is the problem i search but all the solution i found i already made it so what else can be the problem when i try to use console it don't show like it doesn't enter the submit function at all
this is the pieces in my component that work with form
const [editMyText, setEditMyText] = useState({
editIsActive: false,
textValue: body,
});
const inputRef = useRef(null);
const handleSaveEdit = (e) => {
setEditMyText({
editIsActive: false,
textValue: inputRef.current.value,
});
// updatePost(_id, textValue);
};
const handleOnSubmit = (e) => {
e.preventDefault();
console.log('done 1');
updatePost(_id, textValue);
console.log('done 2');
};
{body !== null && !editIsActive ? (
<p
className='card-text'
onClick={(e) => auth.user._id === user && handleEditText(e)}
>
{textValue}
</p>
) : (
<form
className='edit-post-form'
onSubmit={(e) => handleOnSubmit(e)}
>
<textarea
className='edit-text'
defaultValue={textValue}
ref={inputRef}
/>
<button
className='btn btn-raised btn-danger mr-2'
onClick={(e) => handleCloseEdit(e)}
>
Close
</button>
<button
type='submit'
className='btn btn-raised btn-success'
onClick={(e) => handleSaveEdit(e)}
>
Save
</button>
</form>
)}

Edit user information in React

I am using axios to get and post user information, but I am somewhat lost on how to handle editing a user's information. I have created a working put endpoint, but I am lost on how to change to editable text in React
User component:
const handleEdit = (user) => {
axios
.put(`/api/User/${user.id}`)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}
return(
<div className="container white">
<h3 className="center">
User List
<Button className="btn-createUser" color="info">
<Link to='/signup'>Add New User</Link>
</Button>
</h3>
<form className="inline-form">
{users.list.map(user => (
<div className="section" key={user.id}>
<div className="divider"></div>
<h5 className="user-userName">{user.username}</h5>
<h5 className="user-userEmail">{user.email}</h5>
<Button className="btn-delete" color="info" onClick={() => handleDelete(user)}>Delete</Button>
<Button className="btn-edit" color="info" onClick={() => handleEdit(user)}>Edit</Button>
</div>
))}
</form>
</div>
);
const [users] = useState([]); //declare users array at top then use setUsers to update
handleChange = event => {
const index = users.findIndex(user => user.userName = event.target.value);
users[index].userName = event.target.value;
setUsers(users);
}
you need to set userName and userEmail in state first. the onChange method will capture new updates.
<input
type="text"
name="username"
value={this.state.username}
onChange={this.handleChange}
/>
handleChange = event => {
this.setState({ username: event.target.value });
};

Resources