0

I need to pass the state value to a different component and I want to use it in the different component.

for the same problem, I have asked a different question which was closed as duplicate however, I have tried everything mentioned in the previous question. I do not think this is a duplicate question.

This is the some of the code in the first component:

    const handleFormSubmit = async (event) => {
        event.preventDefault()
        console.log(formData)
        try {
            await axios
                .post(`http://localhost:4000/accounts/register`, formData)
                .then(function (response) {
                    console.log(response)
                    console.log(response.data)
                    const newValue = response.data
                    setServerMessage(newValue)
                })
        } catch (error) {
            console.log(error)
        }
        history({
            pathname: '/session/verifyotp',
            state: { serverMessage: serverMessage },
        })
    }
    useEffect(() => {
        if (serverMessage) {
            console.log(serverMessage)
            setServerMessage(serverMessage)
            console.log(serverMessage)
        }
    }, [serverMessage])

The code in the second component where I am trying to access the state.

const navigate = useNavigate()
let data = useLocation()
console.log(data)

This is the complete code in the first page :

import React, { useEffect, useState } from 'react'
import { Box, styled } from '@mui/system'
import { Grid, Button } from '@mui/material'
import { ValidatorForm, TextValidator } from 'react-material-ui-form-validator'
import Typography from '@mui/material/Typography'
import { FormLabel } from '@mui/material'
import Link from '@mui/material/Link'
import axios from 'axios'
import Appbar from '../Appbar'
import Alert from '@mui/material/Alert'
import Snackbar from '@mui/material/Snackbar'
import { useNavigate } from 'react-router-dom'

const FlexBox = styled(Box)(() => ({
    display: 'flex',
    alignItems: 'center',
}))

const JustifyBox = styled(FlexBox)(() => ({
    justifyContent: 'center',
}))

const IMG = styled('img')(() => ({
    width: '100%',
}))

const JWTRegister = styled(JustifyBox)(() => ({
    background: '#ffffff',
    minHeight: '100vh !important',
    input: {
        background: 'white',
        borderRadius: 25,
    },
}))

const JwtRegister = (props) => {
    const [serverMessage, setServerMessage] = useState('')
    const [open, setOpen] = useState(false)
    const history = useNavigate()

    const [formData, setFormData] = useState({
        name: '',
        mobile: '',
        email: '',
        password: '',
    })

    const handleClick = () => {
        setOpen(true)
    }

    const handleClose = (event, reason) => {
        if (reason === 'clickaway') {
            return
        }

        setOpen(false)
    }
    const { name, mobile, email, password } = formData

    const handleChange = (event) => {
        setFormData({
            ...formData,
            [event.target.name]: event.target.value,
        })
    }

    const handleFormSubmit = async (event) => {
        event.preventDefault()
        console.log(formData)
        try {
            await axios
                .post(`http://localhost:4000/accounts/register`, formData)
                .then(function (response) {
                    console.log(response)
                    console.log(response.data)
                    const newValue = response.data
                    setServerMessage(newValue)
                })
        } catch (error) {
            console.log(error)
        }
        history({
            pathname: '/session/verifyotp',
            state: { serverMessage: serverMessage },
        })
    }
    useEffect(() => {
        if (serverMessage) {
            console.log(serverMessage)
            setServerMessage(serverMessage)
            console.log(serverMessage)
        }
    }, [serverMessage])
    return (
        <JWTRegister>
            <Grid container>
                <Appbar />
                <Grid
                    pt={0}
                    pl={10}
                    pr={10}
                    item
                    lg={6}
                    md={6}
                    sm={6}
                    xs={12}
                    sx={{ height: '100vh', backgroundColor: '#3E8BFF' }}
                >
                    <Typography
                        component="h1"
                        variant="h3"
                        sx={{ textTransform: 'none', color: '#000' }}
                    >
                        Sign up
                    </Typography>
                    <Typography component="h1" variant="h5">
                        Register now to get 100 free credits
                    </Typography>
                    {serverMessage ? (
                        <>
                            <Alert
                                variant="filled"
                                autohideduration={6000}
                                severity="success"
                            >
                                {serverMessage.message}
                            </Alert>
                            <Snackbar
                                open={open}
                                autoHideDuration={3000}
                                onClose={handleClose}
                            >
                                <Alert
                                    onClose={handleClose}
                                    severity="success"
                                    sx={{ width: '100%' }}
                                >
                                    {serverMessage.message}
                                </Alert>
                            </Snackbar>
                        </>
                    ) : null}
                    <ValidatorForm id="Register" onSubmit={handleFormSubmit}>
                        <Grid container spacing={2}>
                            <Grid
                                item
                                lg={6}
                                md={6}
                                sm={12}
                                xs={12}
                                sx={{ mt: 2 }}
                            >
                                <FormLabel sx={{ color: '#000000' }}>
                                    Name
                                </FormLabel>
                                <TextValidator
                                    sx={{ mb: 3, width: '100%' }}
                                    size="small"
                                    type="text"
                                    name="name"
                                    value={name}
                                    autoFocus
                                    onChange={handleChange}
                                    validators={['required']}
                                    errorMessages={['Name field is required']}
                                    inputProps={{
                                        style: {
                                            borderRadius: 25,
                                            backgroundColor: 'white',
                                            disableUnderline: true,
                                        },
                                    }}
                                />
                            </Grid>
                            <Grid
                                item
                                lg={6}
                                md={6}
                                sm={12}
                                xs={12}
                                sx={{ mt: 2 }}
                            >
                                <FormLabel sx={{ color: '#000000' }}>
                                    Mobile
                                </FormLabel>
                                <TextValidator
                                    sx={{ mb: 3, width: '100%' }}
                                    size="small"
                                    type="text"
                                    name="mobile"
                                    value={mobile}
                                    onChange={handleChange}
                                    validators={['required']}
                                    errorMessages={[
                                        'Mobile Number field is required',
                                    ]}
                                    inputProps={{
                                        style: {
                                            borderRadius: 25,
                                            backgroundColor: 'white',
                                            disableUnderline: true,
                                        },
                                    }}
                                />
                            </Grid>
                        </Grid>
                        <FormLabel sx={{ color: '#000000' }}>Email</FormLabel>
                        <TextValidator
                            sx={{ mb: 3, width: '100%' }}
                            size="small"
                            type="email"
                            name="email"
                            value={email}
                            onChange={handleChange}
                            validators={['required', 'isEmail']}
                            inputProps={{
                                style: {
                                    borderRadius: 25,
                                    backgroundColor: 'white',
                                    disableUnderline: true,
                                },
                            }}
                            errorMessages={[
                                'Email field is required',
                                'Email is not valid',
                            ]}
                        />
                        <FormLabel sx={{ color: '#000000' }}>
                            Password
                        </FormLabel>
                        <TextValidator
                            sx={{ mb: '16px', width: '100%' }}
                            size="small"
                            name="password"
                            type="password"
                            value={password}
                            onChange={handleChange}
                            validators={['required']}
                            errorMessages={['Password field is required']}
                            inputProps={{
                                style: {
                                    borderRadius: 25,
                                    disableUnderline: true,
                                    backgroundColor: 'white',
                                },
                            }}
                        />
                        <FlexBox pb={2}>
                            <Button
                                type="submit"
                                variant="contained"
                                sx={{
                                    borderRadius: 25,
                                    textTransform: 'none',
                                    background: '#C7FF80',
                                    color: '#000000',
                                }}
                                onClick={handleClick}
                            >
                                Verify OTP
                            </Button>
                        </FlexBox>
                    </ValidatorForm>
                    <Typography
                        variant="subtitle1"
                        display="inline"
                        sx={{
                            textTransform: 'none',
                            color: '#000000',
                        }}
                    >
                        Already a member?
                        <Link
                            href="/session/signin"
                            sx={{
                                textTransform: 'none',
                                color: '#FFFFFF',
                            }}
                        >
                            &nbsp; Sign in &nbsp;
                        </Link>
                        instead.
                    </Typography>
                </Grid>
                <Grid
                    pt={1}
                    pl={10}
                    item
                    lg={6}
                    md={6}
                    sm={6}
                    xs={12}
                    sx={{ height: '100vh', backgroundColor: '#3E8BFF' }}
                >
                    <Typography pb={3} variant="body">
                        or sign up with
                    </Typography>
                    <Grid
                        pb={3}
                        pt={3}
                        container
                        alignItems="center"
                        spacing={2}
                    >
                        <Grid item>
                            <IMG
                                src="/assets/images/signup-linkedin.svg"
                                height={55}
                                width={55}
                            />
                        </Grid>
                        <Grid item>
                            <Typography pb={1} component="h6" variant="h6">
                                Linkedin
                            </Typography>
                        </Grid>
                    </Grid>
                    <Grid pb={3} container alignItems="center" spacing={2}>
                        <Grid item>
                            <IMG
                                src="/assets/images/signup-google.svg"
                                height={55}
                                width={55}
                            />
                        </Grid>
                        <Grid item>
                            <Typography pb={1} component="h6" variant="h6">
                                Google
                            </Typography>
                        </Grid>
                    </Grid>
                    <Grid pb={3} container alignItems="center" spacing={2}>
                        <Grid item>
                            <IMG
                                src="/assets/images/signup-facebook.svg"
                                height={55}
                                width={55}
                            />
                        </Grid>
                        <Grid item>
                            <Typography pb={1} component="h6" variant="h6">
                                Facebook
                            </Typography>
                        </Grid>
                    </Grid>
                    <Grid pb={3} container alignItems="center" spacing={2}>
                        <Grid item>
                            <IMG
                                src="/assets/images/signup-email.svg"
                                height={55}
                                width={55}
                            />
                        </Grid>
                        <Grid item>
                            <Typography component="h6" variant="h6">
                                Corporate Email ID
                            </Typography>
                            <span pb={1} component="h6" variant="h6">
                                (Use only Business email)
                            </span>
                        </Grid>
                    </Grid>
                </Grid>
            </Grid>
        </JWTRegister>
    )
}

export default JwtRegister

This is output I get in the second component:

Object { pathname: "/session/verifyotp", search: "", hash: "", state: null, key: "n1jhatdj" }

No matter what I try I am not able to pass the state to the different component. I have followed this question but does not solve my problem.

How can I access the state value? Why is it coming as null?

Edit:

after I made changes to the history like this:

        history('/session/verifyotp', {
            state: { serverMessage: serverMessage },
        })

I get the following output: serverMessage object is still empty :

hash: ""
​
key: "vi016u6e"
​
pathname: "/session/verifyotp"
​
search: ""
​
state: Object { serverMessage: "" }

Edited: My handleFormSubmit function

    const handleFormSubmit = async (event) => {
        event.preventDefault()
        console.log(formData)
        let newValue
        try {
            const response = await axios.post(
                `http://localhost:4000/accounts/register`,
                formData
            )
            console.log(response)
            console.log(response.data)
            newValue = response.data
            setServerMessage(newValue)
        } catch (error) {
            console.log(error)
        }
        history('/session/verifyotp', {
            state: { serverMessage: serverMessage },
        })
    }
    useEffect(() => {
        if (serverMessage) {
            console.log(serverMessage)
            console.log(serverMessage)
            setServerMessage(serverMessage)
        }
    }, [serverMessage])

error in browser console: enter image description here

JustAG33K
  • 1,403
  • 3
  • 13
  • 28

1 Answers1

1

You need to use your history like this for react-router v6.

history("/session/verifyotp", {
  state: { serverMessage: serverMessage },
});

Check the Documentation. It accepts to and the state as an optional param.

Here is my componentA

import {useNavigate} from 'react-router-dom';

const ComponentA = (props) => {
  const navigate = useNavigate();
  const toComponentB = () => {
    navigate("/componentB", { state: { id: 1, name: "sabaoon" } });
  };
  return (
    <button
      onClick={() => {
        toComponentB();
      }}
    >
      Component B
    </button>
  );
};

export default ComponentA;

You can get the state data in componentB like this.

import { useLocation } from "react-router-dom";

function ComponentB() {
  const location = useLocation();
  return <div>{location?.state?.name}</div>;
}

export default ComponentB;

You can update your handleFormSubmit method like this. You are using both async/await and .then which confuses the users.

const handleFormSubmit = async (event) => {
  event.preventDefault();
  console.log(formData);
  let newValue;
  try {
    const response = await axios.post(
      `http://localhost:4000/accounts/register`,
      formData
    );
    console.log(response);
    console.log(response.data);
    newValue = response.data;
    setServerMessage(newValue);
  } catch (error) {
    console.log(error);
  }
  history({
    pathname: "/session/verifyotp",
    state: { serverMessage: newValue },
  });
};

mc-user
  • 1,769
  • 4
  • 14
  • 25
  • I have made the changes to the history like this: history('/session/verifyotp', { state: { serverMessage: serverMessage }, }) now I get the following out put ``` state: Object { serverMessage: "" } ​​ serverMessage: "" ``` serverMessage is still empty. – JustAG33K Apr 12 '22 at 13:19
  • I have edited the question with the output that I am getting when I edited the history. thanks – JustAG33K Apr 12 '22 at 13:23
  • `setState` is usually asynchronous. It might have been executed before the promise got resolved. Try by giving a callback function to your `setState` variable. Maybe you can try updating your handleSumbit function like this ```await axios.post(`http://localhost:4000/accounts/register`, formData).then(function (response) { const newValue = response.data; setServerMessage(newValue); history("/session/verifyotp", { state: { serverMessage: serverMessage },});}); ``` – mc-user Apr 12 '22 at 13:26
  • Could you provide a working example of the callback function for the setState variable? – JustAG33K Apr 12 '22 at 13:35
  • `setState('value', () => { statements you wanna execute }`. I think you can move your history state to axios call itself. Once you get the response, you can navigate to your requested location. If that API fails, you have already added a catch block. – mc-user Apr 12 '22 at 13:37
  • I do not want to be automatically redirect to the second component. I want to redirect only after click on the button. – JustAG33K Apr 12 '22 at 13:44
  • I have updated the function in the answer. Check whether that satisfies your requirement or share any errors if you get. – mc-user Apr 12 '22 at 13:49
  • Updated the question for some reason the state value is not passing to the second component. attached screenshot of the browser console. – JustAG33K Apr 12 '22 at 13:57
  • Use `newValue` here `history('/session/verifyotp', { state: { serverMessage: newValue }, })` – mc-user Apr 12 '22 at 13:59
  • It work I am getting the following out in browser console: serverMessage: Object { message: "Registration successful, please check your email for verification instructions" } ​​​ message: "Registration successful, please check your email for verification instructions" – JustAG33K Apr 12 '22 at 14:14
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/243826/discussion-between-mchowdam-and-justag33k). – mc-user Apr 12 '22 at 14:16