Page reloading while dispatching a form data - reactjs

I am trying to submit a form data to the reducer via action creators but its not working anyway.The page is reloading anyway.I can't resist.
Below is my code
import React, { Component } from 'react';
import { connect } from 'react-redux'
import {addName} from '../Actions/actionCreators'
class about extends Component {
constructor(props){
super(props)
}
render() {
return (
<div>
<h2> About me </h2>
<form action="" onSubmit={this.submitform}>
<br/>
<input type="text" name="name" placeholder="Your Name" />
<br/>
<input type="submit" value="Submit"/>
</form>
</div>
);
}
}
const mapDispatchToProps = dispatch => {
return{
submitform : (e) => {
dispatch(addName(e.target.name.value))
}
}
}
export default connect(null, mapDispatchToProps)(about)
Here addName is the action creator which receives data(name)
if i am using this,also error happens 'this.props.dispatch` is not a function
constructor(props){
super(props)
this.submithandle = this.submithandle.bind(this)
}
submithandle(e, dispatch){
e.preventDefault()
this.props.dispatch(addName(e.target.name.value))
}
What step i can take to submit data via mapDispatchToProps?

You don't understand mapDispatchToProps correctly. mapDispatchToProps will add the functions to the delivered props of the component. The props of about looks like this:
{submitform: (e) => {dispatch(addName(e.target.name.value))}}
To call the submitform prop, you have to access it with this.props.submitform.
If you write that into your onSubmit prop of form, it should work.
You should also set the names of your react components to start with an upper-case so that react can differentiate them between native and new components. So about => About.
Hope this helps. Happy coding.

You need a handler for the onSubmit event.
this.handleSubmit(e)=>{
this.props.addNameAction(e.target.value);
}
then Dispatch the action that you supposedly imported at the top.
const mapDispatchToProps = dispatch => {
return{
addNameAction : (name) => {
dispatch(addName(name))
}
}
}

Related

Redux Form is not firing off submit function

I have set up a redux form but it does not seem to be firing off onSubmit the actual submitHandle function.
Please see the code below
import React, { Component } from "react";
import { connect } from "react-redux";
import { hideTransferLicenseWindow, setProgressBarValue } from "../../redux/actions/LicenseActions";
import { Field, reduxForm } from 'redux-form'
export class LicenseTransfer extends Component {
componentDidMount() {
console.log(this.props)
}
renderInput = ({ input, customValue, autoFocus }) => {
return (
<input
className="uk-input"
{...input}
value={customValue}
autoFocus={autoFocus}
/>
)
}
onFormSubmit = (values) => {
console.log('Clicked submit')
}
render() {
const { licenseOperations } = this.props;
return (
<div className="app-section transfer-license-window">
<button
onClick={() => this.props.hideTransferLicenseWindow()}
uk-close=""
className="uk-alert-close"
></button>
<form onSubmit={this.props.handleSubmit(this.onFormSubmit)}>
<div className="field">
<label>From:</label>
<Field
name="transferLicenseFromEmail"
component={this.renderInput}
customValue={this.props.userEmail}
/>
</div>
<div className="field">
<label>To:</label>
<Field
name="transferLicenseToEmail"
component={this.renderInput}
autoFocus={true}
/>
</div>
</form>
</div>
);
}
}
const transferLicenseFormWrapper = reduxForm({
form: 'transferLicense',
})(LicenseTransfer)
const mapStateToProps = (state) => {
return {
userEmail: state.user.user.email,
licenseOperations: state.licenseOperations,
};
};
export default connect(mapStateToProps, { hideTransferLicenseWindow, setProgressBarValue })(
transferLicenseFormWrapper
);
So it should log form values on submitting the form but it does not react nor gives any errors/
I have similar form set up in another component which works just fine. Spent good amount of time playing the game of finding differences but this does not makes sense to me.
Thanks
Ok I figured it out.
For those who might have the same issue, make sure to place your submit button inside the Form, if you want to be able to submit by pressing "Enter".
If you just want to submit with a mouse click on button only, it is sufficient to leave the button outside of the form (not sure if there are any other consequences).

page reloads when updating redux state/submitting form

I'm trying to set up a simple react-redux flow where an input updates state and a form submits the value in the component's state to a redux action function. However, whenever the form submits, the page reloads and when I add e.preventDefault() to the submit function, I get
TypeError: e.preventDefault is not a function
I've tried adding e.preventDefault() to the submitToRedux function but when I add do, I get TypeError: e.preventDefault is not a function
Here is my Child1.js:
import React, { useState } from "react";
import { changeName } from "../redux/name/name.actions";
import { connect } from "react-redux";
function Child1(state) {
const [name, setName] = useState("");
const changeHandler = e => {
e.preventDefault();
setName(e.target.value);
};
const submitToRedux = e => {
// e.preventDefault();
changeName(name);
};
return (
<div>
<h2>CHILD ONE</h2>
<form onSubmit={submitToRedux(name)}>
<input type="text" onChange={changeHandler} />
<button type="submit">SUBMIT</button>
<h2>name in Child1 state: {name}</h2>
<h2>name in redux: {state.name.name}</h2>
</form>
</div>
);
}
const mapStateToProps = state => ({
name: state.name
});
export default connect(mapStateToProps)(Child1);
App.js:
import React from "react";
import Child1 from "./components/Child1";
function App() {
return (
<div className="App">
<Child1 />
</div>
);
}
export default App;
root-reducer.js:
import { combineReducers } from "redux";
import nameReducer from "./name/nameReducer";
export default combineReducers({
name: nameReducer
});
and nameReducer.js:
import NameActionTypes from "./name.types";
const INITIAL_STATE = {
name: "Mike"
};
const nameReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case NameActionTypes.CHANGE_NAME:
return {
...state,
name: action.payload
};
default:
return state;
}
};
export default nameReducer;
I expect it to update the state.name.name value in Child1.js to whatever is submitted from the state in the Child1.js component when the form is submitted but instead it just reloads the page and since I'm not persisting it to local storage it just remains blank. When I add e.preventDefault() I expect it to stop reloading the page when the form submits but it then says that
e.preventDefault is not a function
It's because you are not passing the submit event to submitToRedux function.
You should pass it to your function like this:
<form onSubmit={(e) => submitToRedux(e, name)}>
and then you handle it in you function like this:
const submitToRedux = (e, name) => {
e.preventDefault();
changeName(name);
};
Here is how child1.js will be:
import React, { useState } from "react";
import { changeName } from "../redux/name/name.actions";
import { connect } from "react-redux";
function Child1(state) {
const [name, setName] = useState("");
const changeHandler = e => {
e.preventDefault();
setName(e.target.value);
};
const submitToRedux = (e, name) => {
e.preventDefault();
changeName(name);
};
return (
<div>
<h2>CHILD ONE</h2>
<form onSubmit={(e) => submitToRedux(e, name)}>
<input type="text" onChange={changeHandler} />
<button type="submit">SUBMIT</button>
<h2>name in Child1 state: {name}</h2>
<h2>name in redux: {state.name.name}</h2>
</form>
</div>
);
}
const mapStateToProps = state => ({
name: state.name
});
export default connect(mapStateToProps)(Child1);
Multiple issue's with your code,
First, you are writing state as argument to Child1 component
function Child1(state) {
which should be,
function Child1(props) {
You should set this props to your state,
const [name, setName] = useState(props.name);
Your input should be controlled,
<input type="text" onChange={changeHandler} value={name} />
You should print name like this,
<h2>name in Child1 state: {name}</h2>
<h2>name in redux: {props.name}</h2>
Your form submit method should be like this,
<form onSubmit={submitToRedux}>
And finally your submitToRedux function,
const submitToRedux = e => {
e.preventDefault(); //Now this will work
changeName(name); //As we have controlled input, we direclty take name from state
};
You just need to pass the function that will get called once the form is submitted.
<form onSubmit={submitToRedux}>
But instead you are actually calling it right away:
<form onSubmit={submitToRedux(name)}>
When you just pass the function, the form will take care of calling it with a submit event as parameter.
In your code the error says the parameter e should contain a function preventDefault, which clearly is not defined in the variable you are passing in as parameter when you do: submitToRedux(name)

How to preventDefault() on form onSubmit in react/redux project

I have a component with an input that when submitted is meant to pass the input text to store. I can't figure out how to preventDefault() when I submit the form.
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { addItem } from '../actions';
const ItemInput = (props) => {
return (
<div>
<form onSubmit={() => props.addItem('test')}>
<input
placeholder="addItem"
/>
</form>
</div>
);
}
const mapStateToProps = (state) => {
return { addItem: state.addItem };
}
export default connect(mapStateToProps, {
addItem: addItem
})(ItemInput);
I know how to do this in react, but it doesn't seem to work the same way, I keep getting an unexpected token error that doesn't make any sense, probably because the syntax just doesn't work the same way with redux and store. This also isn't a button issue, I'm submitting the form after pressing return.
This part of your code is just a function, you can expand it as you want:
<form onSubmit={() => props.addItem('test')}>
So, you can do:
<form onSubmit={e => {
e.preventDefault();
props.addItem('test');
}}>
Or move this handler into a function:
const handleSubmit = e => {
e.preventDefault();
props.addItem('test');
}
// ...
<form onSubmit={handleSubmit}>

How to read updated state in react-redux app?

I am learning Redux and trying to Add/View users using redux in my react app.By using 'ref' in react, I am reading the payload(name,account_number) of new user and passing to 'addProfile' action creator onClick of 'Add' button in this way -
AddView.js
import React from 'react';
import { connect } from 'react-redux';
import { addProfile } from '../actions';
class AddView extends React.Component{
addValues(){
return(
<div>
Name : <input type="text" value={this.props.profiles.name} ref={el => this.nameValue=el}/>
Account Number : <input type="text" value={this.props.profiles.account_number} ref={el => this.accountValue=el}/>
<button onClick={() => this.props.addProfile(this.nameValue,this.accountValue)}>Add</button>
</div>
);
}
render(){
return (
<div>
Add Profile
<br /><br />
{this.addValues()}
</div>
);
}
}
const mapStateToProps = (state) => {
return { profiles : state.profiles }
}
export default connect(mapStateToProps, {addProfile}) (AddView);
Now am trying to console log the name,account_number in my action creator but I get html instead of values.
export const addProfile = (name, account_number) => {
console.log(name,account_number)
return{
type :'ADD_PROFILE',
payload : {
name : name,
account_number : account_number
}
};
}
Can anyone please help where I went wrong. Full code here - https://codesandbox.io/s/239j97y36p
React refs give you a ref to the dom element, if you just want the value of the input you can get it with .value. I would also rename your ref variables then to be accurate like nameInputRef and accountInputRef.
Name :{" "}
<input
type="text"
value={this.props.profiles.name}
ref={el => (this.nameInputRef = el)}
/>
Account Number :{" "}
<input
type="text"
value={this.props.profiles.account_number}
ref={el => (this.accountInputRef = el)}
/>
<button
onClick={() =>
this.props.addProfile(this.nameInputRef.value, this.accountNumberRef.value)
}
> Add
</button>
You can see full sample adapted from yours here: https://codesandbox.io/s/k3mp28lr3o
class UserProfile extends Component {
constructor(props) {}
render() {
// ref={el => this.nameValue=el} to access input variable
// or
// use onChange event which fire another dispatcher which mutate profile state since we assign input values to profile state you can use state to get latest values
//this.props.profiles
//this.props.onAddProfile()
}
}
const mapStateToProps = state => {
return {
profiles : state.profiles
}
}
const mapDispatchToProps = dispatch => {
return {
onAddProfile:dispatch(addProfile())
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(UserProfile);
You are assigning the element into the variable during the onclick event.
ref={el => this.nameValue=el}
You can use a local state to store the value of the while onChange instead of ref
npm install redux-thunk --save
profile.jsx
class Profile extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<input
type="text"
onChange={({ target }) =>
this.props.onUsernameUpdated(target.value)
}
value={this.props.profile.username}
placeholder="Username"
/>
<input
type="text"
onChange={({ target }) =>
this.props.onAccNumberUpdated(target.value)
}
value={this.props.profile.accNumber}
placeholder="Account Number"
/>
<button onclick={this.props.onUpdateProfile}>Submit</button>
</div>
)
}
}
const mapStateToProps = state => {
return {
profile: state.profile
};
};
const mapDispatchToProps = dispatch => {
return {
onUsernameUpdated: username => dispatch(usernameUpdated(username)),
onAccNumberUpdated: password => dispatch(accNumberUpdated(accNumber)),
onUpdateProfile: () => dispatch(updateProfile())
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Profile);
actions.js
export function usernameUpdated(username) { // need reducer to update state profile name
return {
type: 'USER_NAME_UPDATE',
data: username
}
}
export function accNumberUpdated(accNumber) { // need reducer to update state profile acc number
return {
type: 'ACC_NUM_UPDATE',
data: accNumber
}
}
export function updateProfile() {
return (dispatch, getState) => { //thunk magic
// latest profile after user input
const profile = getState().profile
}
}

React and Redux: Using state or refs?

I'm currently teaching my self Redux. For this purpose I created a simple Todo application. Now on this application I'm currently at the process of using dispatch() to put a todo into my store. This is a question about your opinion. I want to avoid code smell.
I found two ways of achieving this. One using state and one using ref. I was wondering which way is better? Thank you for any advice. The two versions are below.
Version one using ref:
import React, { Component } from "react";
import Todo from "./Todo";
import { connect } from "react-redux";
import { ADD_TODO } from "./actionCreators";
class TodoList extends Component {
taskRef = React.createRef();
handleSubmit = event => {
event.preventDefault();
this.props.dispatch({
type: ADD_TODO,
task: this.taskRef.current.value
});
event.currentTarget.reset();
};
render() {
let todos = this.props.todos.map((val, index) => (
<Todo task={val.task} key={index} />
));
return (
<div>
<form onSubmit={this.handleSubmit}>
<label htmlFor="task">Task </label>
<input type="text" name="task" id="task" ref={this.taskRef} />
<button type="submit">Add a Todo!</button>
</form>
<ul>{todos}</ul>
</div>
);
}
}
const mapDispatchToProps = state => ({
todos: state.todos
});
export default connect(mapDispatchToProps)(TodoList);
And here is the second version using state:
import React, { Component } from "react";
import Todo from "./Todo";
import { connect } from "react-redux";
import { ADD_TODO } from "./actionCreators";
class TodoList extends Component {
state = {
task: ""
};
handleSubmit = event => {
event.preventDefault();
this.props.dispatch({
type: ADD_TODO,
task: this.state.task
});
event.target.reset();
};
handleChange = event => {
event.persist();
this.setState((state, props) => ({
[event.target.name]: event.target.value
}));
};
render() {
let todos = this.props.todos.map((val, index) => (
<Todo task={val.task} key={index} />
));
return (
<div>
<form onSubmit={this.handleSubmit}>
<label htmlFor="task">Task </label>
<input
type="text"
name="task"
id="task"
onChange={this.handleChange}
/>
<button type="submit">Add a Todo!</button>
</form>
<ul>{todos}</ul>
</div>
);
}
}
const mapDispatchToProps = state => ({
todos: state.todos
});
export default connect(mapDispatchToProps)(TodoList);
EDIT: As qasimalbaqali pointed out in the comments here is a similar post on stackoverflow. I'm still unsure, because the first answer says refs are bad with reasons, the second one says React Devs say refs are awesome for grabbing values from the dom (which is what I'm doing!).
Thank you for anyone helping. It seems like a majority of the community is in favor of using state.
I also asked Dan Abramov, who said that he'd prefer a ref in this case.
You can see his answer here.
Thank you everyone for your input and advice! :)

Resources