React Too many re-renders - javascript

I am following the serverless-stack.com tutorial. But I am stuck after creating the login button.
I keep getting the error:
Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
I don't know what is causing the render so many times.
I combined my LoaderButton instead of importing to make it simpler.
import React, { useState } from "react";
import { Auth } from "aws-amplify";
import { useHistory } from "react-router-dom";
import { FormGroup, FormControl, ControlLabel } from "react-bootstrap";
import { useFormFields } from "../libs/hooksLib";
import { onError } from "../libs/errorLib";
import "../css/index.css";
const LoaderButton = (
isLoading,
className = "",
disabled = false,
...props ) => {
return(
<Button
className={`LoaderButton ${className}`}
disabled={disabled || isLoading}
{...props}
>
{isLoading && <Glyphicon glyph="refresh" className="spinning" />}
{props.children}
</Button>
)
};
export default function Login() {
let history = useHistory();
const [isLoading, setIsLoading] = useState(false);
const [fields, handleFieldChange] = useFormFields({
email: "",
password: ""
});
function validateForm() {
return fields.email.length > 0 && fields.password.length > 0;
}
async function handleSubmit(event) {
event.preventDefault();
setIsLoading(true);
try {
await Auth.signIn(fields.email, fields.password);
userHasAuthenticated(true);
console.log(history);
//history.push("/");
} catch (e) {
onError(e);
setIsLoading(false);
}
}
return (
<div className="Login">
<form onSubmit={ () => { handleSubmit() } }>
<FormGroup controlId="email" bsSize="large">
<ControlLabel>Email</ControlLabel>
<FormControl
autoFocus
type="email"
value={fields.email}
onChange={ () => { handleFieldChange() } }
/>
</FormGroup>
<FormGroup controlId="password" bsSize="large">
<ControlLabel>Password</ControlLabel>
<FormControl
type="password"
value={fields.password}
onChange={ () => { handleFieldChange() } }
/>
</FormGroup>
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={ () => { isLoading() } }
disabled={() => { !validateForm() }}
>
Login
</LoaderButton>
</form>
</div>
);
}
hooksLib.js / useFormFields
import { useState } from 'react'
const useFormFields = (initalState) => {
const [fields, setValues] = useState(initalState)
return [
fields,
setValues({
...fields,
[event.target.id]: event.target.value
})
]
}
export { useFormFields }

Your custom hook should look like this if you want to accept the event value:
const useFormFields = (initalState) => {
const [fields, setValues] = useState(initalState)
return [
fields,
(event) => setValues({
...fields,
[event.target.id]: event.target.value
})
]
}
Since that parameter is actually a callback that should occur.
Also, your LoadingButton implementation needs to change to this:
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={isLoading} // This is a boolean value, not a function
disabled={() => !validateForm()}
>...</LoaderButton>

Related

why the createRef current always null in react

I am developing a simple edit app page, because the form.item initial value did not update by data, so I want to setFieldsValue in the antd 4.x, this is my code looks like:
import React from 'react'
import { Modal, Input, Form } from 'antd'
export default function EditApp(props) {
const { visible, rowData: data = {}, onVisibleChange, onEdit, dispatch } = props
const [form] = Form.useForm()
let formRef = React.createRef()
if(formRef.current){
formRef.current.setFieldsValue({
remark: data?data.remark:''
})
}
function onConfirm() {
form.validateFields()
.then(values => {
let localValues = {
...values,
appId: data.app_id
}
onEdit(localValues)
})
.catch(info => {
console.log('Validate Failed:', info)
})
}
function onCancel() {
onVisibleChange()
}
return (
<>
<Modal title='Edit App' visible={visible} onOk={onConfirm} onCancel={onCancel}>
<Form form={form} ref={formRef}>
<Form.Item
label='remark'
name='remark'
value={data?data.remark:''}
>
<Input placeholder='Please input remark' />
</Form.Item>
</Form>
</Modal>
</>
)
}
To my surprise, the formRef.current is always null. Am I missing something? what should I do to make the Form.Item value update by data which passed from other component?
CreateRef work only with class components , you can use the hooks useRef if your react versions support it
import React, {useRef} from 'react'
import { Modal, Input, Form } from 'antd'
export default function EditApp(props) {
const { visible, rowData: data = {}, onVisibleChange, onEdit, dispatch } = props
const [form] = Form.useForm()
const formRef = useRef();
if(formRef.current){
formRef.current.setFieldsValue({
remark: data?data.remark:''
})
}
function onConfirm() {
form.validateFields()
.then(values => {
let localValues = {
...values,
appId: data.app_id
}
onEdit(localValues)
})
.catch(info => {
console.log('Validate Failed:', info)
})
}
function onCancel() {
onVisibleChange()
}
return (
<>
<Modal title='Edit App' visible={visible} onOk={onConfirm} onCancel={onCancel}>
<Form form={form} ref={formRef}>
<Form.Item
label='remark'
name='remark'
value={data?data.remark:''}
>
<Input placeholder='Please input remark' />
</Form.Item>
</Form>
</Modal>
</>
)
}
this could fix it too:
React.useEffect(() => {
form.setFieldsValue({
remark:data?data.remark:''
});
});
when using useEffect, ref code should be removed.

I keep getting Can't perform a React state update on an unmounted component

I keep getting this error for two of my React components and i can't figure it out. I just started to learn to use hooks and I can't seem to fix this error message.
I tried searching online and going through a few suggested methods but it doesn't seem to work for me.
I saw an article saying to add this code below but it has no effect at all.
let mounted = true
return function cleanup() {
mounted = false
}
Here's the two errors:
"index.js:1 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
in BoardAdmin (at App.js:125)
in component (at PrivateRoute.js:9)"
"Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
in SFTPList (at CsvExtractor.js:206)
in div (created by Col)
in Col (at CsvExtractor.js:205)
in div (created by Row)
in Row (at CsvExtractor.js:183)
in form (created by Form)
in Form (at CsvExtractor.js:129)
in CsvExtractor (at BoardAdmin.js:30)
in header (at BoardAdmin.js:29)
in div (at BoardAdmin.js:28)
in BoardAdmin (at App.js:125)
in component (at PrivateRoute.js:9)"
csvextractor.js
import React, { useState, useEffect, useRef } from 'react';
import Dropzone from 'react-dropzone';
import MultiSelect from 'react-multiple-select-dropdown-lite';
import 'react-multiple-select-dropdown-lite/dist/index.css';
import 'react-datepicker/dist/react-datepicker.css';
import DatePicker from 'react-datepicker';
import SFTPList from './SFTPDownload';
import { Form, Row, Col, Button } from 'react-bootstrap';
import FileService from '../services/file.service';
import { history } from '../helpers/history';
const CsvExtractor = () => {
const [file, setFile] = useState(null); // state for storing actual file
const [details, setDetails] = useState({
title: '',
description: '',
});
const [errorMsg, setErrorMsg] = useState('');
const dropRef = useRef(); // React ref for managing the hover state of droppable area
const [startDate, setStartDate] = useState(new Date());
const [endDate, setEndDate] = useState(null);
const [filters, setFilters] = useState([]);
const filterOptions = [
{
value: 'translate',
label: 'Translate to EN',
},
{
value: 'emailentrant',
label: 'Email Entrant',
},
{
value: 'emailsortant',
label: 'Email Sortant',
},
{
value: 'appelentrant',
label: 'Appel Entrant',
},
{
value: 'appelsortant',
label: 'Appel Sortrant',
},
{
value: 'chat',
label: 'Chat',
},
];
const handleSelect = (selections) => {
setDetails({
...details,
description: `${selections}`,
});
setFilters(selections.split(','));
};
const handleInputChange = (event) => {
setDetails({
...details,
[event.target.name]: event.target.value,
});
};
const onDrop = (files) => {
const [uploadedFile] = files;
setFile(uploadedFile);
const fileReader = new FileReader();
fileReader.onload = () => {};
fileReader.readAsDataURL(uploadedFile);
dropRef.current.style.border = '2px dashed #e9ebeb';
};
const onChange = (dates) => {
const [start, end] = dates;
const tdate = end === null ? '' : end.toString().slice(4, 15);
setDetails({
...details,
title: `${start.toString().slice(4, 15)} - ${tdate}`,
});
setStartDate(start);
setEndDate(end);
};
const updateBorder = (dragState) => {
if (dragState === 'over') {
dropRef.current.style.border = '2px solid #000';
} else if (dragState === 'leave') {
dropRef.current.style.border = '2px dashed #e9ebeb';
}
};
const handleOnSubmit = async (event) => {
event.preventDefault();
try {
const { title, description } = details;
if (title.trim() !== '' && description.trim() !== '') {
if (file) {
const formData = new FormData();
formData.append('startDate', startDate);
formData.append('endDate', endDate);
formData.append('filters', filters);
formData.append('file', file);
formData.append('title', title);
formData.append('description', description);
setErrorMsg('');
await FileService.uploadFile(formData);
history.push('/list');
} else {
setErrorMsg('Please select a file to add.');
}
} else {
setErrorMsg('Please enter all the field values.');
}
} catch (error) {
error.response && setErrorMsg(error.response.data);
}
};
return (
<React.Fragment>
<Form className="search-form">
{errorMsg && <p className="errorMsg">{errorMsg}</p>}
<Row>
<Col>
<Form.Group controlId="title">
<Form.Control
type="text"
name="title"
value={details.title || ''}
placeholder="Enter title"
onChange={handleInputChange}
/>
</Form.Group>
</Col>
</Row>
<Row>
<Col>
<Form.Group controlId="description">
<Form.Control
type="text"
name="description"
value={details.description || ''}
placeholder="Enter description"
onChange={handleInputChange}
/>
</Form.Group>
</Col>
</Row>
<Row>
<Col>
<div>
<h5>Select date range</h5>
</div>
<DatePicker
selected={startDate}
onChange={onChange}
startDate={startDate}
endDate={endDate}
selectsRange
inline
/>
</Col>
<Col>
<h5>Select filters (at least one)</h5>
<MultiSelect
style={{ backgroundColor: 'white', marginTop: '10px' }}
onChange={handleSelect}
options={filterOptions}
/>
</Col>
</Row>
<Row>
<Col xs={12}>
{/* <div className="upload-section"> */}
<Dropzone
onDrop={onDrop}
onDragEnter={() => updateBorder('over')}
onDragLeave={() => updateBorder('leave')}
>
{({ getRootProps, getInputProps }) => (
<div {...getRootProps({ className: 'drop-zone' })} ref={dropRef}>
<input {...getInputProps()} />
<p>Drag and drop a file OR click here to select a file</p>
{file && (
<div>
<strong>Selected file:</strong> {file.name}
</div>
)}
</div>
)}
</Dropzone>
{/* </div> */}
</Col>
<Col>
<SFTPList />
</Col>
</Row>
<Button variant="primary" type="submit" onClick={handleOnSubmit}>
Submit
</Button>
</Form>
</React.Fragment>
);
};
export default CsvExtractor;
adminboard.js is below
import React, { useState, useEffect, useRef } from 'react';
import 'react-multiple-select-dropdown-lite/dist/index.css';
import 'react-datepicker/dist/react-datepicker.css';
import UserService from '../services/user.service';
import CsvExtractor from './CsvExtractor';
const BoardAdmin = () => {
const [content, setContent] = useState('');
useEffect(() => {
UserService.getAdminBoard().then(
(response) => {
setContent(response.data);
},
(error) => {
const _content =
(error.response && error.response.data && error.response.data.message) ||
error.message ||
error.toString();
setContent(_content);
},
);
}, []);
return (
<div className="container">
<header className="jumbotron">
<CsvExtractor />
</header>
</div>
);
};
export default BoardAdmin;
If fixed it with the code below
const [filesList, setFilesList] = useState([]);
const [errorMsg, setErrorMsg] = useState('');
useEffect(() => {
const source = axios.CancelToken.source();
const getFilesList = async () => {
try {
const { data } = await axios.get('api/file/getallfiles/', {
headers: authHeader(),
cancelToken: source.token,
});
setErrorMsg('');
setFilesList(data);
} catch (error) {
if (axios.isCancel(error)) {
} else {
error.response && setErrorMsg(error.response.data);
}
}
};
getFilesList();
return () => {
source.cancel();
};
}, []);

React view only gets fresh data on page reload?

I'm building a simple campgrounds CRUD app to get some practice with the MERN stack and Redux.
Adding a campground is working fine. I'm routing to the campgrounds list page after adding a campground. But unless I reload the page, fresh data isn't retrieved.
I figured it has something to do with React's lifecycle methods.
Code:
manageCampground.js
import React, { Component } from 'react';
import TextField from '#material-ui/core/TextField';
import Card from '#material-ui/core/Card';
import Button from '#material-ui/core/Button';
import '../../styles/addCampground.css';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import {
actionAddCampground,
getCampgroundDetails,
actionUpdateCampground
} from './actions/campgroundActions';
class AddCampground extends Component {
constructor(props) {
super(props);
this.state = {
name: '',
description: '',
cost: ''
};
}
componentDidMount() {
const campground = this.props.campground;
if (campground._id) {
this.props.getCampgroundDetails(campground._id);
this.setState({
name: campground.name,
description: campground.description,
cost: campground.cost
});
}
}
handleChange = e => {
const { name, value } = e.target;
this.setState({
[name]: value
});
};
addCampground = () => {
const name = this.state.name;
const description = this.state.description;
const cost = this.state.cost;
this.props.actionAddCampground({
name,
description,
cost
});
this.props.history.push('/home');
console.log('Campground added successfully');
};
updateCampground = () => {
const name = this.state.name;
const description = this.state.description;
const cost = this.state.cost;
this.props.actionUpdateCampground({
name,
description,
cost
});
this.props.history.push('/home');
console.log('Updated successfully');
};
render() {
console.log(this.props);
return (
<Card className="add-campground-card">
<TextField
name="name"
className="textfield"
label="Campground name"
variant="outlined"
value={this.state.name}
onChange={e => this.handleChange(e)}
/>
<TextField
name="description"
className="textfield"
label="Campground description"
variant="outlined"
value={this.state.description}
onChange={e => this.handleChange(e)}
/>
<TextField
name="cost"
className="textfield"
type="number"
label="Campground cost"
variant="outlined"
value={this.state.cost}
onChange={e => this.handleChange(e)}
/>
{!this.props.campground._id ? (
<Button
variant="contained"
color="primary"
onClick={this.addCampground}>
Add Campground
</Button>
) : (
<Button
variant="contained"
color="primary"
className="update-campground-btn"
onClick={this.updateCampground}>
Update Campground
</Button>
)}
</Card>
);
}
}
const mapStateToProps = state => {
return {
campground: state.campgroundList.singleCampground || ''
};
};
const mapDispatchToProps = dispatch => {
return bindActionCreators(
{
actionAddCampground,
getCampgroundDetails,
actionUpdateCampground
},
dispatch
);
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(AddCampground);
campgroundList.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getAllCampgrounds } from './actions/campgroundActions';
import Header from '../common/Header';
import Card from '#material-ui/core/Card';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardActions from '#material-ui/core/CardActions';
import CardContent from '#material-ui/core/CardContent';
import Button from '#material-ui/core/Button';
import Typography from '#material-ui/core/Typography';
import { Link } from 'react-router-dom';
import { bindActionCreators } from 'redux';
import '../../styles/landingPage.css';
class CampgroundLanding extends Component {
componentDidMount() {
this.props.getAllCampgrounds();
console.log('From component did mount');
}
render() {
const { campgrounds } = this.props;
return (
<>
<Header />
{campgrounds.map(campground => (
<Card className="campground-card" key={campground._id}>
<CardActionArea>
<CardContent>
<Typography gutterBottom variant="h5"
component="h2">
{campground.name}
</Typography>
<Typography variant="body2" color="textSecondary"
component="p">
{campground.description}
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<Link
style={{ textDecoration: 'none', color: 'white' }}
to={`/campgrounds/${campground._id}`}>
<Button size="small" color="primary">
View Details
</Button>
</Link>
<Button size="small" color="primary">
Learn More
</Button>
</CardActions>
</Card>
))}
<Link
style={{ textDecoration: 'none', color: 'white' }}
to="/campgrounds/add">
<Button color="primary">Add Campground</Button>
</Link>
</>
);
}
}
const mapStateToProps = state => {
return {
campgrounds: state.campgroundList.campgrounds
};
};
const mapDispatchToProps = dispatch => {
return bindActionCreators(
{
getAllCampgrounds
},
dispatch
);
};
export default connect(
mapStateToProps,
null
)(CampgroundLanding);
campgroundActions.js
import {
GET_ALL_CAMPGROUNDS,
ADD_CAMPGROUND,
GET_CAMPGROUND_DETAILS,
EDIT_CAMPGROUND
} from '../actionTypes/types';
import axios from 'axios';
const API_URL = `http://localhost:5000/api`;
export const getAllCampgrounds = () => {
return dispatch => {
axios
.get(`${API_URL}/campgrounds`)
.then(res => {
dispatch({
type: GET_ALL_CAMPGROUNDS,
payload: res
});
})
.catch(err => console.log(err));
};
};
export const actionAddCampground = campground => {
return dispatch => {
axios
.post(`${API_URL}/campgrounds`, campground)
.then(res => {
console.log(res);
dispatch({
type: ADD_CAMPGROUND,
payload: res
});
})
.catch(err => console.log(err));
};
};
export const getCampgroundDetails = id => {
return dispatch => {
axios
.get(`${API_URL}/campgrounds/${id}`)
.then(res => {
dispatch({
type: GET_CAMPGROUND_DETAILS,
payload: res
});
})
.catch(err => console.log(err));
};
};
export const actionUpdateCampground = id => {
return dispatch => {
axios
.put(`${API_URL}/campgrounds/${id}`)
.then(res => {
console.log(res);
dispatch({
type: EDIT_CAMPGROUND,
payload: res
});
})
.catch(err => console.log(err));
};
};
campgroundReducers.js
import {
GET_ALL_CAMPGROUNDS,
ADD_CAMPGROUND,
GET_CAMPGROUND_DETAILS,
EDIT_CAMPGROUND
} from '../actionTypes/types';
const initialState = {
campgrounds: []
};
export default (state = initialState, action) => {
switch (action.type) {
case GET_ALL_CAMPGROUNDS:
const { campgroundList } = action.payload.data;
state.campgrounds = campgroundList;
return {
...state
};
case ADD_CAMPGROUND:
const { campground } = action.payload.data;
return {
...state,
campground
};
case GET_CAMPGROUND_DETAILS:
const { singleCampground } = action.payload.data;
return { ...state, singleCampground };
case EDIT_CAMPGROUND:
const { editedCampground } = action.payload.data;
return { ...state, editedCampground };
default:
return state;
}
};
If I'm using componentDidUpdate, it's leading to infinite loop.
componentDidUpdate(prevProps) {
if (prevProps.campgrounds !== this.props.campgrounds) {
this.props.getAllCampgrounds();
}
}
I know I'm going wrong somewhere, but I can't figure out where.
You have to fix your componentDidUpdate method to avoid this infinity loop. Your are trying to compare objects via === method which will always fail according to this example:
const a = {key: 1}
const b = {key: 1}
console.log(a === b); // false
You could use for example isEqual method from lodash module to compare objects like you want https://lodash.com/docs/4.17.15#isEqual
console.log(_.isEqual({key: 1}, {key: 1})) // true
console.log({key: 1} === {key: 1}) // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
Actually why do you want refresh data in this case? When you add object with success into the store this will refresh your component so you don't have to request for fresh data.

Formik's handleChange throws "TypeError: null is not an object (evaluating '_a.type')" on DateInput's onChange

When I just add the handleChange from Formik to the "semantic-ui-calendar-react" DateInput component I get the following error on selection a date.
https://imgur.com/a/BOEDEXc "console output"
AddWishlistFormDate.tsx
import { FormikErrors, FormikProps, withFormik } from 'formik';
import * as React from 'react';
import { DateInput } from 'semantic-ui-calendar-react';
import { Button, Form } from 'semantic-ui-react';
export interface FormValues {
date: string;
}
interface Props {
submit: (values: FormValues) => Promise<FormikErrors<FormValues> | null>;
}
class C extends React.PureComponent<FormikProps<FormValues> & Props> {
public render() {
const {
values: { date },
handleChange,
handleSubmit,
} = this.props;
return (
<Form onSubmit={handleSubmit}>
<Form.Field>
<label>Date</label>
<DateInput
name="date"
value={date}
iconPosition="left"
onChange={handleChange}
/>
</Form.Field>
<Button type="submit">Add</Button>
</Form>
);
}
}
export const AddWishlistFormDate = withFormik<Props, FormValues>({
mapPropsToValues: () => ({ date: '' }),
handleSubmit: async (values, { props, setErrors }) => {
const errors = await props.submit(values);
if (errors) {
setErrors(errors);
}
},
})(C);
run it with following
const handleSubmit = async (values: FormValues) => {
console.log(values);
return null;
};
return <AddWishlistFormDate submit={handleSubmit} />;
You would do it like this
<DateInput
name="date"
value={date}
iconPosition="left"
onChange={(_, {value}) => setFieldValue('date', value)}
/>

_this2.props.signup is not a function in React Redux app

Please note that I've already checked answers in this question and nothing seems to work.
I'm using this repo as a boilerplate. Instead of firebase database, I'm trying to send username and email with the firebase auth userid , to the node server. I created an action creator signup to handle this.
This is signup.js action creator
import * as types from '../constants/action_types';
import axios from 'axios';
export const signup = (user) => {
console.log(user);
return async dispatch => {
try {
const response = await axios.get('http://localhost:5000/api/user/register', user)
const data = await {response};
dispatch({
type : types.SIGN_UP,
payload : data.fromback
})
} catch (error) {
console.lot(error)
}
}
}
Then I've connected it with the component with mapDispatchToProps., So,under the SignUpPage component, React dev tools shows signup as a function. But when it get triggers, it gives an error saying _this2.props.signup is not a function Why's that ?
This is my SignUpPage component
import React, { Component } from 'react';
import {
Link,
withRouter,
} from 'react-router-dom';
import { auth } from '../../firebase';
import * as routes from '../../constants/routes';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import {signup} from './../../actions/signup';
const SignUpPage = ({ history }) =>
<div>
<h1>SignUp</h1>
<SignUpForm history={history} />
</div>
const updateByPropertyName = (propertyName, value) => () => ({
[propertyName]: value,
});
const INITIAL_STATE = {
username: '',
email: '',
passwordOne: '',
passwordTwo: '',
error: null,
};
class SignUpForm extends Component {
constructor(props) {
super(props);
this.state = { ...INITIAL_STATE };
}
onSubmit = (event) => {
const {
username,
email,
passwordOne,
} = this.state;
const {
history,
} = this.props;
auth.doCreateUserWithEmailAndPassword(email, passwordOne)
.then(authUser => {
const userid = authUser.user.uid;
const user = { email, userid };
this.props.signup(user);
})
.catch(error => {
this.setState(updateByPropertyName('error', error));
});
event.preventDefault();
}
render() {
const {
username,
email,
passwordOne,
passwordTwo,
error,
} = this.state;
const isInvalid =
passwordOne !== passwordTwo ||
passwordOne === '' ||
username === '' ||
email === '';
return (
<form onSubmit={this.onSubmit}>
<input
value={username}
onChange={event => this.setState(updateByPropertyName('username', event.target.value))}
type="text"
placeholder="Full Name"
/>
<input
value={email}
onChange={event => this.setState(updateByPropertyName('email', event.target.value))}
type="text"
placeholder="Email Address"
/>
<input
value={passwordOne}
onChange={event => this.setState(updateByPropertyName('passwordOne', event.target.value))}
type="password"
placeholder="Password"
/>
<input
value={passwordTwo}
onChange={event => this.setState(updateByPropertyName('passwordTwo', event.target.value))}
type="password"
placeholder="Confirm Password"
/>
<button disabled={isInvalid} type="submit">
Sign Up
</button>
{ error && <p>{error.message}</p> }
</form>
);
}
}
const SignUpLink = () =>
<p>
Don't have an account?
{' '}
<Link to={routes.SIGN_UP}>Sign Up</Link>
</p>
const mapDispatchToProps = dispatch => bindActionCreators({ signup }, dispatch)
export default connect(null, mapDispatchToProps)(withRouter(SignUpPage));
export {
SignUpForm,
SignUpLink,
};
Its not a prop,
you've imported it as a function,
you can directly use it as function like this
import {signup} from './../../actions/signup';
.....
auth.doCreateUserWithEmailAndPassword(email, passwordOne)
.then(authUser => {
const userid = authUser.user.uid;
const user = { email, userid };
signup(user);
})
.catch(error => {
this.setState(updateByPropertyName('error', error));
});

Categories

Resources