React js redirect not redirecting - javascript

For some reason, I can't understand redirect is not working.
I don't get any error.
The Redirect is called from react-router-dom library
in the console I see the xxx.
** added **
for some reason the redirect returns an error
this is the redirect block:
redirectUser = (json) => {
console.log('json', json);
console.log('state', this.state);
if(this.state.auth == true){
localStorage.setItem('userid', json.userid);
localStorage.setItem('auth', this.state.auth);
console.log('xxx');
return <Redirect to='/biblist' />
}
}
this is the file data from chrome dev sources:
this is the entire component.
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { connect } from 'react-redux';
import { Redirect, Link } from 'react-router-dom';
import {
Button,
Form,
FormGroup,
FormControl,
Col,
Alert,
Checkbox,
ControlLabel,
HelpBlock,
Grid,
Row
} from 'react-bootstrap';
import { userLogedIn } from '../../actions';
class LoginForm extends Component {
constructor() {
super();
this.state={
username: '',
password: '',
data: [],
auth: false,
usernameError: '',
passwordError: '',
EmptyUsernameError: '',
EmptyPasswordError: ''
}
this.onSubmitLogin = this.onSubmitLogin.bind(this);
this.onChange = this.onChange.bind(this);
}
componentWillMount(){
console.log('mount', this.props);
}
componentDidUpdate(){
console.log('Update', this.props);
console.log('Update username', this.props.userid);
}
clientValidate = () => {
let isError = false;
if(this.state.username === ''){
isError = true;
this.setState({EmptyUsernameError: 'לא הזנתם שם משתמש'});
}
if(this.state.password === ''){
isError = true;
this.setState({EmptyPasswordError: 'לא הזנתם סיסמה'});
}
return isError;
}
validate = () => {
let isError = false;
if(this.state.auth === false){
isError = true;
this.setState({usernameError: 'אחד הפרטים שהזנתם שגוי'});
}
return isError;
}
onSubmitLogin(event){
event.preventDefault();
if(this.clientValidate()){
this.clientValidate();
}else{
fetch('http://127.0.0.1/bibli/api/user_switch/' + this.state.username +
'/'+ this.state.password )
.then(response => response.json())
.then(json => {
if(json.count > 0)
{
this.setState({auth: true});
this.props.userLogedIn(json);
this.redirectUser(json);
}else{
let isError = true;
this.validate();
this.setState({
auth: false,
data: null
});
}
})
.catch(error => console.log('parsing faild', error))
}
}
redirectUser = (json) => {
console.log('json', json);
console.log('state', this.state);
if(this.state.auth == true){
localStorage.setItem('userid', json.userid);
localStorage.setItem('auth', this.state.auth);
console.log('xxx');
debugger
return <Redirect to='/biblist' />
}
}
onChange(event){
this.setState({
[event.target.name]: event.target.value,
auth: false,
usernameError: '',
EmptyPasswordError: '',
EmptyUsernameError: ''
})
}
render() {
return (
<Grid fluid id="LoginForm" className="yellow-bg">
<Row className="show-grid">
<Col xsOffset={2} xs={8} mdOffset={3} md={6}>
<h2 className="text-center">כבר רשומים? התחברו!</h2>
<Form horizontal>
<FormGroup controlId="formHorizontalusername">
<Col xs={12} sm={4}>
<FormControl ref="username" name="username" type="text" onChange={this.onChange} placeholder="הקלד דואר אלקטרוני"/>
</Col>
<Col xs={12} sm={4}>
<FormControl ref="password" name="password" type="password" onChange={this.onChange} placeholder="הקלד סיסמא"/>
</Col>
<Col xs={12} sm={4} >
<Button onClick={this.onSubmitLogin} type="submit" className="full-width-btn" id="loginSubmit">התחבר</Button>
</Col>
</FormGroup>
{
this.state.EmptyUsernameError ?
<Alert variant="danger"> {this.state.EmptyUsernameError} </Alert> :
''
}
{
this.state.EmptyPasswordError ?
<Alert variant="danger"> {this.state.EmptyPasswordError} </Alert> :
''
}
{
this.state.usernameError ?
<Alert variant="danger"> {this.state.usernameError} </Alert> :
''
}
<small><Link to="/register">אינך רשום? הרשם!</Link></small>
</Form>
</Col>
</Row>
</Grid>
);
}
}
const mapDispatchToProps = dispatch => {
return {
userLogedIn: (params) => dispatch(userLogedIn(params))
};
};
const mapStateToProps = state => {
return {
userid: state.authReducer.userid,
auth: state.authReducer.auth
}
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);

You could try with "withRouter" HOC
Example :
import { withRouter } from 'react-router-dom'
const Button = ({ history }) => (
<button
type='button'
onClick={() => { history.push('/new-location') }}
>
Click Me!
</button>
)
export default withRouter(Button)

Related

How to add validations for formik form with material UI

I am new to the formik and I am trying to add validations .
I have container which is like :
export default class ForgotPasswordContainer extends React.Component<
RouteComponentProps,
MyState
> {
constructor(props) {
super(props)
this.state = {
error: '',
success: ''
}
}
forgotPasswordSuccess = async result => {
if (result.Status === 'Successful') {
this.setState({
success: strings.emailSuccess
})
} else if (result.Status === 'Failed') {
this.setState({
error: result.ErrorAdmin
})
}
}
forgotPassword = async ({ variables }) => {
console.log(variables)
const url = `url to change password`
console.log(url)
try {
const result: any = await fetch(url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
mode: 'no-cors'
}
})
return {
data: {
login: await result.json()
}
}
} catch (err) {
this.setState({
error:
err?.response?.data?.error_description || err.message || strings.genericError
})
throw err
}
}
render() {
const { forgotPassword, forgotPasswordSuccess } = this
return (
<ForgotPasswordPage
onSubmit={forgotPassword}
error={this.state.error}
onForgotPasswordSuccess={forgotPasswordSuccess}
OnSuccess={this.state.success}
backgroundImage={LoginBackground}
logo={logo}
/>
)
}
}
Now in the ForgotPasswordPage component
((withFormik as any)({
mapPropsToValues: () => ({ username: '' })
validationSchema: Yup.object().shape({
username: Yup.string().required('Username is required!')
}),
handleSubmit: (values, { setSubmitting, props }) => {
const { onSubmit, onForgotPasswordSuccess } = props
onSubmit({ variables: values }).then(
result => {
setSubmitting(false)
onForgotPasswordSuccess(result.data.login)
},
() => {
setSubmitting(false)
}
)
},
displayName: 'LoginForm'
}))
export default class ForgotPasswordPage extends React.Component<MyProps> {
render() {
const {
error,
values,
touched,
errors,
dirty,
isSubmitting,
handleChange,
handleBlur,
handleSubmit,
logo,
headerLabel,
backgroundImage,
OnSuccess
} = this.props
return (
<Card
style={{ background: `url(${backgroundImage})` }}
className={css.backgroundCard}
alignItem='center'
justifyContent='center'>
<Card
className={css.loginCard}
variant='standard'
alignItem='center'
direction='column'>
{logo ? (
<Icon imageSrc={logo} className={css.logo} />
) : (
<div>
<div>
<Typography variant='h1'>{headerLabel}</Typography>
</div>
<div>
<Typography variant='h1'>Forgot Password</Typography>
</div>
</div>
)}
<form onSubmit={handleSubmit} className={css.loginForm}>
<Input
variant='standard'
textAlign='center'
placeholder='Username'
id='username'
name='username'
type='text'
value={values.username}
onChange={handleChange}
onBlur={handleBlur}
autoFocus
error={errors.username && touched.username}
/>
{error && (
<Typography variant='caption' classes={css.errorMsg}>
{error}
</Typography>
)}
{OnSuccess && (
<Typography variant='caption' classes={css.successMsg}>
{OnSuccess}
</Typography>
)}
<Button
variant='primary'
theme='light'
type='submit'
disabled={!dirty || isSubmitting || !!errors.username}>
<Typography variant='h1'>Send Password</Typography>
</Button>
</form>
</Card>
</Card>
)
}
}
Now Here in this form I am trying to do few things like
adding validations , such that password and repeat password should be same
and that is required . on Success of onSummit clear form.
How to add the validations in this form ?
Thanks,
You can use yup library https://www.npmjs.com/package/yup. The library works well with formik, here you can see how to build easy validation form.
https://formik.org/docs/guides/validation
You can update validationSchemalike this:
validationSchema: Yup.object().shape({
username: Yup.string().required('Username is required!'),
password: Yup.string()
.min(7)
.max(255)
.required("Password is required"),
confirmPassword: Yup.string()
.min(7)
.max(255)
.oneOf([Yup.ref("password")], "Password's not match")
.required("Required!"),
})

Clicking like icons increases the like count of other components

Upon the click of a single like, it is increasing the number of likes for both separate components. What is causing both like numbers to increase, and how can I code it to where only one like number increases upon clicking a like?
I have also include the console in the picture below where I have console logged the logic in my reducer. You can find the code for the reducer further below the picture.
Reducer code
import { GET_GOALS, GOAL_ERROR, UPDATE_LIKES } from "../actions/types";
const initialState = {
goals: [],
goal: null,
loading: true,
error: {}
};
export default function(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case GET_GOALS:
return {
...state,
goals: payload,
loading: false
};
case GOAL_ERROR:
return {
...state,
error: payload,
loading: false
};
case UPDATE_LIKES:
return {
...state,
goals: state.goals.map(goal =>
console.log("goal id", goal._id) === console.log("payload id", payload.goalId) ? { ...goal, likes: payload.likes } : goal
),
loading: false
};
default:
return state;
}
}
Action code
import axios from "axios";
import { GET_GOALS, GOAL_ERROR, UPDATE_LIKES } from "./types";
// Get goals
export const getGoals = () => async dispatch => {
try {
const res = await axios.get("/api/goal/goalfeed");
dispatch({
type: GET_GOALS,
payload: res.data
});
} catch (error) {
dispatch({
type: GOAL_ERROR,
payload: { msg: error.response }
});
}
};
// Add like
export const addLike = goalId => async dispatch => {
try {
const res = await axios.put(`/api/goal/like/${goalId}`);
dispatch({
type: UPDATE_LIKES,
payload: { goalId, likes: res.data }
});
} catch (error) {
dispatch({
type: GOAL_ERROR,
payload: { msg: error.response }
});
}
};
// Remove like
export const removeLike = goalId => async dispatch => {
try {
const res = await axios.put(`/api/goal/unlike/${goalId}`);
dispatch({
type: UPDATE_LIKES,
payload: { goalId, likes: res.data }
});
} catch (error) {
dispatch({
type: GOAL_ERROR,
payload: { msg: error.response }
});
}
};
Goals component code
import React, { useEffect } from "react";
import Moment from "react-moment";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { addLike, removeLike } from "../../actions/goal";
import { getGoals } from "../../actions/goal";
import Spinner from "../layout/Spinner";
import Navbar from "../dashboard/Navbar";
import ThumbUpAltIcon from "#material-ui/icons/ThumbUpAlt";
import ThumbDownAltIcon from "#material-ui/icons/ThumbDownAlt";
import ChatIcon from "#material-ui/icons/Chat";
import DeleteIcon from "#material-ui/icons/Delete";
import DoneIcon from "#material-ui/icons/Done";
import {
Typography,
Container,
CssBaseline,
makeStyles,
Grid,
Avatar,
Paper,
Button
} from "#material-ui/core";
const useStyles = makeStyles(theme => ({
paper: {
height: "auto",
marginBottom: theme.spacing(3)
},
actionButtons: {
marginTop: "3vh"
},
profileHeader: {
textAlign: "center",
marginBottom: 20
},
avatar: {
width: theme.spacing(7),
height: theme.spacing(7)
}
}));
const Goals = ({
getGoals,
auth,
addLike,
removeLike,
goal: { goals, user, loading }
}) => {
useEffect(() => {
getGoals();
}, [getGoals]);
const classes = useStyles();
return loading ? (
<>
<Navbar />
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Spinner />
</div>
</Container>
</>
) : (
<>
<CssBaseline />
<Navbar />
<main>
<Container>
<Typography variant="h2" className={classes.profileHeader}>
Goals
</Typography>
{/* parent grid */}
<Grid container spacing={4}>
{goals.map(singleGoal => (
<Grid
className={classes.paper}
key={singleGoal._id}
spacing={1}
container
item
direction="row"
alignItems="center"
component={Paper}
>
<Grid
item
container
direction="column"
justify="center"
alignItems="center"
xs={3}
>
<Avatar className={classes.avatar} src={singleGoal.avatar} />
<Typography variant="caption">
{singleGoal.first_name} {singleGoal.last_name}
</Typography>
<Typography variant="caption" className={classes.postedOn}>
Posted on{" "}
<Moment format="MM/DD/YYYY">{singleGoal.date}</Moment>
</Typography>
</Grid>
<Grid container item direction="column" xs={9}>
<Typography variant="body1">{singleGoal.text}</Typography>
<Grid item className={classes.actionButtons}>
<Button size="small" onClick={e => addLike(singleGoal._id)}>
<ThumbUpAltIcon />
</Button>
<Typography variant="caption">
{singleGoal.likes.length}
</Typography>
<Button
size="small"
onClick={e => removeLike(singleGoal._id)}
>
<ThumbDownAltIcon />
</Button>
<Button href={`/goal/${singleGoal._id}`} size="small">
<ChatIcon />
</Button>
{!auth.loading && singleGoal.user === auth.user._id && (
<Button size="small">
<DoneIcon />
</Button>
)}
{!auth.loading && singleGoal.user === auth.user._id && (
<Button size="small">
<DeleteIcon />
</Button>
)}
</Grid>
</Grid>
</Grid>
))}
</Grid>
</Container>
</main>
</>
);
};
Goals.propTypes = {
getGoals: PropTypes.func.isRequired,
goal: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
goal: state.goal,
auth: state.auth
});
export default connect(mapStateToProps, { getGoals, addLike, removeLike })(
Goals
);
There exists a flaw in your conditional test.
state.goals.map(goal =>
console.log("goal id", goal._id) === console.log("payload id", payload.goalId) // What is this? it will always evaluate to true
? { ...goal, likes: payload.likes }
: goal
)
console.log('EQUAL?', console.log() === console.log()); // true
console.log('EQUAL?', console.log(3) === console.log(3)); // true
console.log('EQUAL?', console.log(3) === console.log('three')); // true
console.log('EQUAL?', console.log('apple') === console.log({})); // true
console.log('EQUAL?', console.log(42) === console.log(-42)); // true
The function console.log is a void return, i.e. undefined, so you are comparing undefined === undefined, which is always true.
console.log(undefined === undefined); // true
You are spreading in the new 'likes' value to every goal object.
Try instead:
state.goals.map(
goal => goal._id === payload.goalId
? { ...goal, likes: payload.likes }
: goal
)

How to fix rerendering after select option from react multiple-select?

I can't solve why my input is rerendered when I dynamically add next input. In first step I click on select employe from multiple select and input is dynamically created with id and name of employee.Now I can add allocation for employee but when I add next employee. Allocation value of first employee is removed.
1.Step
2.Step
3.Step
4.Step
Component ProjectForm (I deleted some unnecessary parts of this code for this question )
export default class ProjectForm extends Component {
constructor(props) {
super(props);
const { project, timurProjects } = this.props;
this.state = {
employees:
project && project.currentEmployees ? project.currentEmployees : [],
technologies:
project && project.technologies
? project.technologies.map(mapToId)
: [],
allTimurProjects: timurProjects,
allocationValue:
project && project.currentEmployees ? project.currentEmployees : [],
projectTimur: null,
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleUpdateEmployees = this.handleUpdateEmployees.bind(this);
this.handleUpdateTechnologies = this.handleUpdateTechnologies.bind(this);
}
componentDidMount() {
const { project } = this.props;
const { allTimurProjects } = this.state;
this.setState({
projectTimur: allTimurProjects.find(projectTimur => {
return project ? projectTimur.code === project.code : false;
}),
});
}
handleSubmit = values => {
const { submitProjectForm, project, successText } = this.props;
const { employees, technologies, projectTimur } = this.state;
const value = {
...values,
code: projectTimur ? projectTimur.code : null,
projectManagerId: projectTimur
? projectTimur.projectManager.id
: values.projectManager,
};
return submitProjectForm(
value,
employees,
technologies,
(project && project.id) || null,
)
.then(res => {
displayNotification(successText, 'success');
const { id } = res.data.project;
browserHistory.push(`/projects/detail/${id}`);
})
.catch(error => {
throw new SubmissionError(error.response.data.error);
});
};
handleUpdateEmployees(employees) {
this.setState({
employees,
});
}
handleUpdateTechnologies(technologies) {
this.setState({
technologies,
});
}
handleUpdateAllocation = allocValue => {
console.log(allocValue, 'ALLOCAVALUE');
this.setState({
allocationValue: allocValue,
});
};
render() {
const {
projectData,
project,
handleSubmit,
error,
pristine,
submitting,
title,
submitText,
} = this.props;
const {
employees,
technologies,
projectTimur,
allTimurProjects,
allocationValue,
} = this.state;
const employeesPristine = isEqual(
employees,
project && project.currentEmployees ? project.currentEmployees : [],
);
const technologiesPristine = isEqual(
technologies,
project && project.technologies ? project.technologies.map(mapToId) : [],
);
const allocationValuePristine = isEqual(
allocationValue,
project && project.currentEmployees ? project.currentEmployees : [],
);
const formPristine =
employeesPristine &&
technologiesPristine &&
pristine &&
allocationValuePristine;
const defaultPMValue = projectTimur
? projectTimur.projectManager.name
: '--';
const owners =
projectTimur && projectTimur.owner.name ? [projectTimur.owner] : [];
const projectManagers = projectTimur
? [projectTimur.projectManager]
: projectData.projectManagers;
return (
<Container>
<Row>
<Col>
<Card className="card-project-add hs-box-shadow mx-auto">
<CardHeader>
{project ? (
<Row>
<Col>
<FontAwesome icon={['fab', 'product-hunt']} /> {title}
</Col>
<Col className="text-right">
<Link to={`/projects/detail/${project.id}`}>
Show project detail
</Link>
</Col>
</Row>
) : (
<span>
<FontAwesome icon={['fab', 'product-hunt']} /> {title}
</span>
)}
</CardHeader>
<CardBody>
{error && <Alert color="danger">{error}</Alert>}
<Form
onSubmit={handleSubmit(this.handleSubmit)}
onKeyPress={blockSubmitOnEnter}
>
<FormRow>
</Col>
<Col xs="12" lg="5">
<Employees
title="Project employees"
employees={projectData.employees}
defaultValue={
(project && project.currentEmployees) || []
}
onUpdate={this.handleUpdateEmployees}
/>
<EmployeeAllocationTable
title="Project skills/technologies"
employees={employees}
project={project}
onUpdateAllocation={this.handleUpdateAllocation}
defaultValue={
(project && project.currentEmployees) || []
}
/>
</Col>
</FormRow>
<FormRow>
<Col xs="12" md="4" lg="3">
<Button
block
color="success"
type="submit"
disabled={formPristine || submitting}
>
{submitText}
</Button>
</Col>
<Col className="text-md-right mt-3 mt-md-2">
<RequiredFieldsNote />
</Col>
</FormRow>
</Form>
</CardBody>
</Card>
</Col>
</Row>
</Container>
);
}
}
Component Employee
import PropTypes from 'prop-types';
import Select from 'react-select';
import { FormGroup } from 'reactstrap';
import { getFilteredEmployees } from '../../../util/employees';
class Employees extends Component {
handleChange(selectedOptions) {
const { onUpdate } = this.props;
onUpdate &&
onUpdate(
selectedOptions.map(option => ({
id: option.value,
label: option.label,
})),
console.log(selectedOptions, 'SEL'),
);
}
render() {
const { title, employees } = this.props;
let { defaultValue } = this.props;
defaultValue = defaultValue.map(employee => ({
value: employee.id,
label: employee.fullNameInverted || '[unknown name]',
allocationValue: employee.allocationValue,
}));
console.log(defaultValue, 'DV');
const filteredEmployees = getFilteredEmployees(employees);
const options = filteredEmployees.map(employee => ({
value: employee.id,
label: employee.fullNameInverted,
allocationValue: employee.allocationValue,
}));
return (
<FormGroup>
<label>{title}</label>
<Select
defaultValue={defaultValue}
isMulti
options={options}
onChange={this.handleChange.bind(this)}
/>
</FormGroup>
);
}
}
Employees.propTypes = {
title: PropTypes.any,
employees: PropTypes.array.isRequired,
defaultValue: PropTypes.array,
onUpdate: PropTypes.func,
};
export default Employees;
Component.EmployeeAllocationTable
import { Table, Input } from 'reactstrap';
export default class EmployeeAllocationTable extends Component {
constructor(props) {
super(props);
let { defaultValue } = this.props;
defaultValue = defaultValue.map(employee => ({
value: employee.id,
label: employee.fullNameInverted || '[unknown name]',
allocationValue: employee.allocationValue,
}));
this.state = {
value: defaultValue,
key: defaultValue,
allocationValue: '',
};
console.log('State', this.state);
}
handleChangeInput = e => {
const { employees } = this.props;
const { name, value } = e.target;
console.log(name, 'Name', value, 'Value');
const employeesList =
employees &&
employees.find(
employeeLabel => employeeLabel.id.toString() === e.target.name,
);
employeesList.allocationValue = e.target.value;
e.preventDefault();
this.props.onUpdateAllocation(employeesList.allocationValue);
this.setState({
[name]: value,
});
};
render() {
const { employees } = this.props;
const newEmployeesTable =
employees &&
employees.map(employee => {
const employeesList =
employees &&
employees.find(employeeLabel => employeeLabel.id === employee.id);
return (
<tr key={employee.id}>
<td>{employeesList.fullName || employeesList.label}</td>
<td>{employeesList.allocationValue} %</td>
<td>
<Input
name={employee.id.toString()}
value={employee.allocationValue}
onChange={this.handleChangeInput}
placeholder="Allocation on the project (%) "
maxLength="3"
/>
</td>
</tr>
);
});
return (
<div>
<Table>
<thead>
<tr>
<th>Name</th>
<th>Allocation on the project</th>
</tr>
</thead>
<tbody>{newEmployeesTable}</tbody>
</Table>
</div>
);
}
}
What is this?
const employeesList =
employees &&
employees.find(employeeLabel => employeeLabel.id === employee.id);
upd: if you dont want to rerender table you should not call onUpdate prop (handleUpdateEmployees) from on Select change
also you can do something with object
onUpdate(
selectedOptions.map(option => ({
id: option.value,
label: option.label,
//add here allocation and input value
})),

How to pass props from a reusable form in React

I'm building a reusable form in React to be used as login and signin forms in may app.
I'm using Axios to send the data to the database.
But I can't send the input values as props to my UserSignIn component to use them in a function with Axios. Here's the code :
How do I get these props ? Thanks
AccountForm component :
import React, { Component } from "react";
import {Grid,Input, InputLabel, FormControl, Typography, Button, Paper,
} from "#material-ui/core";
class AccountForm extends Component {
constructor(props) {
super(props);
this.state = {
userSignUpName: "",
userSignUpEmail: ""
}
handleChange(e) {
this.setState({
[e.target.id]: e.target.value
});
}
render() {
const {
classes,
formType,
onCreateAccount,
onSubmit,
onBlurCheck,
message,
title
} = this.props;
const {
userSignUpName,
userSignUpEmail,
} = this.state;
return (
<div>
<Grid container justify="center">
<Grid item xs={10}>
<Paper>
<form
onChange={e => this.handleChange(e)}
onSubmit={onSubmit}
>
<Typography variant="subheading" color="primary"
align="center">
{title}
</Typography>
{formType === "signin" && (
<FormControl>
<InputLabel htmlFor="name">Nom</InputLabel>
<Input id="userSignUpName" name="name" type="text" />
</FormControl>
)}
<FormControl>
<InputLabel htmlFor="email">Email</InputLabel>
<Input id="userSignUpEmail" type="email" name="email" />
</FormControl>
</form>
</Paper>
</Grid>
</Grid>
</div>
);
}
}
export default AccountForm;
UserSignIn component :
import React, { Component } from "react";
import axios from "axios";
import config from "../../assets/lib/axiosConfig";
import { AccountForm } from "./Index";
class UserSignIn extends Component {
constructor(props) {
super(props);
this.state = {
formType: "signin",
title: "Create account"
};
}
handleSubmit(e) {
e.preventDefault();
axios(
config(
{
name: this.props.userSignUpName,
email: this.props.userSignUpEmail,
},
"/createAccount",
"post"
)
).then(res => {
const { success, error, token } = res.data;
if (success) {
localStorage.setItem("AuthToken", token);
this.props.redirectTo();
}
if (error) {
this.setState({ message: error });
}
});
}
render() {
const { prevPath, history, userSignUpName } = this.props;
// I can't get userSignUpName props
const { formType, message, title } = this.state;
return (
<AccountForm
{...this.props}
title={title}
onSubmit={e => this.handleSubmit(e)}
formType={formType}
redirectTo={
prevPath !== null && prevPath === "/mycart"
? () => history.push("/payment")
: () => history.push("/")
}
/>
);
}
}
export default UserSignIn;
Thanks
You can pass form data as handleSubmit parameters
AccountForm component :
<form
onChange={e => this.handleChange(e)}
onSubmit={(e) => {
e.preventDefault()
onSubmit({
userSignUpName: this.state.userSignUpName,
userSignUpEmail: this.state.userSignUpEmail,
})
}}
>
UserSignIn component :
handleSubmit(params) {
axios(
config(
{
name: params.userSignUpName,
email: params.userSignUpEmail,
},
//....
}

How to pass input from React Form to Axios get request and display the request result?

I am trying to take input from a user and pass that input into an axios get, when this is done the resultant information is passed into an array that will be displayed as cards.
I am having an issue where the code below is compiling but when enter values into the form fields and press submit, nothing occurrs. Nothing shows up in the web console either.
Where abouts am I going wrong?
const initial_state = {
location: "",
cuisine: "",
searchResults: []
};
class SearchMealForm extends Component {
constructor(props) {
super(props);
this.state = { ...initial_state };
}
//handle user input and inject it into yelp api get request
handleSubmit = event => {
event.preventDefault();
const { location, cuisine, searchResults} = this.state;
this.props.onFormSubmit(this.state(location, cuisine, searchResults));
axios.get(`https://api.yelp.com/v3/businesses/search?location=${location}+IE&categories=${cuisine}`)
.then(response => this.setState({searchResults}))
};
handleChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
//YELP http api get request
searchYelpRestaurants = (location, cuisine, searchResults) => {
axios
.get(
`https://api.yelp.com/v3/businesses/search?location=${location}+IE&categories=${cuisine}`,
{
headers: {
Authorization: `Bearer ${process.env.REACT_APP_API_KEY_YELP}`
}
}
)
.then(res => this.setState({ searchResults: res.data.businesses }));
};
render() {
const { location, cuisine } = this.state;
//create cards with the results from the Yelp API GET
const YelpSearchResults = this.state.searchResults.map(result => {
return (
<div className="ResultCard">
<Card style={{ width: "18rem" }}>
<Card.Img variant="top" src={result.image_url} />
<Card.Body>
<Card.Title>{result.name}</Card.Title>
</Card.Body>
<ListGroup className="list-group-flush">
<ListGroupItem>{result.categories}</ListGroupItem>
<ListGroupItem>{result.rating}</ListGroupItem>
</ListGroup>
<Button variant="primary">Book restaurant</Button>
</Card>
</div>
);
});
// return YelpSearchResults;
// }
return (
<React.Fragment>
<div className="SearchMeal">
<Form onSubmit={this.handleSubmit}>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>City</Form.Label>
<Form.Control
name="location"
type="text"
value={location}
onChange={this.handleChange}
placeholder="location"
/>
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Cuisine</Form.Label>
<Form.Control
name="cuisine"
type="text"
value={cuisine}
onChange={this.handleChange}
placeholder="cuisine"
/>
</Form.Group>
</Form.Row>
<Button>Submit</Button>
<Button>Clear</Button>
</Form>
</div>
{YelpSearchResults}
</React.Fragment>
);
}
}
export default SearchMealForm;
here Button type should be specified as submit
<Button type="submit">Submit</Button>
in order for form submit to work!
I would refactor your component to be functional
import React, { useState } from "react";
import ReactDOM from "react-dom";
import axios from "axios";
import {
Col,
Form,
Card,
Button,
ListGroup,
ListGroupItem
} from "react-bootstrap";
const initial_state = {
location: "",
cuisine: "",
searchResults: []
};
const SearchMealForm = ({ onFormSubmit = () => {} }) => {
const [state, setState] = useState(initial_state);
//handle user input and inject it into yelp api get request
const handleSubmit = async event => {
event.preventDefault();
const { location, cuisine } = state;
onFormSubmit(state);
const searchResults = await searchYelpRestaurants({ location, cuisine });
setState({ ...state, searchResults });
};
const handleChange = event => {
setState({
...state,
[event.target.name]: event.target.value
});
};
//YELP http api get request
const searchYelpRestaurants = async ({ location, cuisine }) => {
try {
const { data: { businesses: searchResults } = {} } = await axios.get(
`https://api.yelp.com/v3/businesses/search?location=${location}+IE&categories=${cuisine}`,
{
headers: {
Authorization: `Bearer dBMqyRFmBBg7DMZPK9v3rbGHmrLtlURpNUCJP6gbYHtyHTmboF-Mka-ZkHiDNq-G9ktATohJGD5iKQvelOHg3sDorBDiMgnsaa8SzTH8w6hjGQXlaIexDxFlTW3FXXYx`
}
}
);
return searchResults;
} catch (err) {
console.error(err);
}
return [];
};
const { location, cuisine, searchResults } = state;
//create cards with the results from the Yelp API GET
const YelpSearchResults = searchResults.map(result => (
<div className="ResultCard">
<Card style={{ width: "18rem" }}>
<Card.Img variant="top" src={result.image_url} />
<Card.Body>
<Card.Title>{result.name}</Card.Title>
</Card.Body>
<ListGroup className="list-group-flush">
<ListGroupItem>{result.categories}</ListGroupItem>
<ListGroupItem>{result.rating}</ListGroupItem>
</ListGroup>
<Button variant="primary">Book restaurant</Button>
</Card>
</div>
));
return (
<React.Fragment>
<div className="SearchMeal">
<Form onSubmit={handleSubmit}>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>City</Form.Label>
<Form.Control
name="location"
type="text"
value={location}
onChange={handleChange}
placeholder="location"
/>
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Cuisine</Form.Label>
<Form.Control
name="cuisine"
type="text"
value={cuisine}
onChange={handleChange}
placeholder="cuisine"
/>
</Form.Group>
</Form.Row>
<Button type="submit">Submit</Button>
<Button>Clear</Button>
</Form>
</div>
{YelpSearchResults}
</React.Fragment>
);
};
export default SearchMealForm;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Categories

Resources