I am trying to build a login form in React.js. I want to enable/disable Login button based on results return by validate method. React throws error 'Invalid value for prop disabled on tag. Either remove it from the element, or pass a string or number value to keep it in the DOM.'. Does anyone have came across same error? Help me to understand what is going wrong here?
import React, { Component } from "react";
import Input from "../common/input";
import Joi from "joi-browser";
class LoginForm extends Component {
state = {
account: {
username: "",
password: "",
},
errors: {},
};
schema = {
username: Joi.string().required().label("Username"),
password: Joi.string().required().label("Password"),
};
abortEarly = {
abortEarly: false,
};
handleSubmit = (event) => {
event.preventDefault();
const errors = this.validate();
if (errors) return;
console.log("submitted");
};
validate = () => {
const result = Joi.validate(
this.state.account,
this.schema,
this.abortEarly
);
const errors = {};
if (!result.error) return null;
result.error.details.map((detail) => {
errors[detail.path[0]] = detail.message;
return detail.path[0];
});
// console.log(errors);
this.setState({ errors });
return errors;
};
validateProperty = ({ name, value }) => {
const propertyTobeValidated = { [name]: value };
const schema = { [name]: this.schema[name] };
const { error } = Joi.validate(propertyTobeValidated, schema);
return error ? error.details[0].message : null;
};
handleChange = ({ currentTarget }) => {
const errors = { ...this.state.errors };
const error = this.validateProperty(currentTarget);
if (error) errors[currentTarget.name] = error;
else delete errors[currentTarget.name];
const account = { ...this.state.account };
account[currentTarget.name] = currentTarget.value;
this.setState({ account, errors });
};
render() {
const { account, errors } = this.state;
return (
<div>
<h1>Login</h1>
<form onSubmit={this.handleSubmit}>
<Input
label="Username"
name="username"
value={account.username}
onChange={this.handleChange}
error={errors.username}
></Input>
<Input
label="Password"
name="password"
value={account.password}
onChange={this.handleChange}
error={errors.password}
></Input>
<button disabled={this.validate} className="btn btn-primary">
Login
</button>
</form>
</div>
);
}
}
export default LoginForm;
Disabled is a boolean property, meaning it can only have a value of true or false. Instead of a boolean, your validate function is returning an object, thus React throws an "Invalid value" error. In order to fix this you could check if the result of this.validate is null:
<button
disabled={(this.validate() !== null)}
className="btn btn-primary"
>
Login
</button>
Also, you forgot to call your this.validate at all :)
Regarding the "Maximum update depth...", you should remove the this.setState from the this.validate, because you are already putting the error in state in the handleChange method.
Here you go with a solution
import React, { Component } from "react";
import Input from "../common/input";
import Joi from "joi-browser";
class LoginForm extends Component {
state = {
account: {
username: "",
password: "",
},
errors: {},
};
schema = {
username: Joi.string().required().label("Username"),
password: Joi.string().required().label("Password"),
};
abortEarly = {
abortEarly: false,
};
handleSubmit = (event) => {
event.preventDefault();
const errors = this.validate();
if (errors) return;
console.log("submitted");
};
validate = () => {
const result = Joi.validate(
this.state.account,
this.schema,
this.abortEarly
);
const errors = {};
if (!result.error) return false;
result.error.details.map((detail) => {
errors[detail.path[0]] = detail.message;
return detail.path[0];
});
// console.log(errors);
this.setState({ errors });
return true;
};
validateProperty = ({ name, value }) => {
const propertyTobeValidated = { [name]: value };
const schema = { [name]: this.schema[name] };
const { error } = Joi.validate(propertyTobeValidated, schema);
return error ? error.details[0].message : null;
};
handleChange = ({ currentTarget }) => {
const errors = { ...this.state.errors };
const error = this.validateProperty(currentTarget);
if (error) errors[currentTarget.name] = error;
else delete errors[currentTarget.name];
const account = { ...this.state.account };
account[currentTarget.name] = currentTarget.value;
this.setState({ account, errors });
};
render() {
const { account, errors } = this.state;
return (
<div>
<h1>Login</h1>
<form onSubmit={this.handleSubmit}>
<Input
label="Username"
name="username"
value={account.username}
onChange={this.handleChange}
error={errors.username}
></Input>
<Input
label="Password"
name="password"
value={account.password}
onChange={this.handleChange}
error={errors.password}
></Input>
<button disabled={this.validate} className="btn btn-primary">
Login
</button>
</form>
</div>
);
}
}
export default LoginForm;
validate method should return boolean (true or false)
Related
Can someone explain why this validation is not working properly? When I click the submit button I should check to see if the field is empty, if it is it should display the error and prevent the next page. If the form has been filled in, then no message should display and clicking the button will take you to a new screen. Currently, the error displays whether or not the field is filled in and the page does not advance in either case.
import React, { Component } from 'react'
const intialState = {
account: "",
accountError: ""
};
export class LandingPage extends Component {
state = intialState;
handleChange = event => {
this.setState({
})
}
continue = e => {
e.preventDefault();
this.props.nextStep();
}
validate = () => {
let accountError= "";
if (!this.state.name) {
accountError = "You must enter an account number!";
}
if (accountError) {
this.setState({ accountError });
return false;
}
return true;
};
handleSubmit = event => {
event.preventDefault();
const isValid = this.validate();
if (isValid) {
console.log(this.state);
this.setState(intialState);
}
};
previous = e => {
e.preventDefault();
this.props.previousStep();
}
render() {
const { values } = this.props;
const { errors } = this.props;
return (
<div>
<h1>Enter an account number</h1>
<input
type="text"
required="required"
placeholder="Enter Account Number"
autoComplete='off'>
</input>
<div className="footer">
<button onClick={this.validate}>Submit</button>
</div>
<div>
{this.state.accountError}
</div>
</div>
)
}
}
export default LandingPage;
The issue is that the name in the state was not getting any value. Fix it like below.
Change the initialState to have the name field
const intialState = {
...
...
name: ""
};
handleChange needs to set the value from the event.
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
Update the validate function to handle the case when input is typed.
validate = () => {
let accountError = "";
if (!this.state.name) {
accountError = "You must enter an account number!";
}
if (accountError) {
this.setState({ accountError });
return false;
}
this.setState({ accountError: "" });
return true;
};
Add the handleChange as the onChange to the input element.
<input
...
...
...
name="name"
onChange={this.handleChange}
></input>
Working Example
How can I convert a Class Component which extends another Class component in a Functional Component in ReactJS?
input.jsx [Functional Component]
const Input = ({ name, label, error, ...rest }) => {
return (
<div className="mb-3">
<label htmlFor={name} className="form-label">
{label}
</label>
<input
autoFocus
{...rest}
id={name}
name={name}
className="form-control"
/>
{error && <div className="alert alert-danger">{error}</div>}
</div>
)
}
export default Input
form.jsx [Class Component]
import React, { Component } from "react"
import Input from "./input"
import Joi from "joi"
class Form extends Component {
state = {
data: {},
errors: {}
}
validate = () => {
const options = { abortEarly: false }
const schemaJoi = Joi.object(this.schema)
const { error } = schemaJoi.validate(this.state.data, options)
if (!error) return null
const errors = {}
error.details.map(item => (errors[item.path[0]] = item.message))
return errors
}
validateProperty = ({ name, value }) => {
const obj = { [name]: value }
const schema = {
[name]: this.schema[name]
}
const schemaJoi = Joi.object(schema)
const { error } = schemaJoi.validate(obj)
return error ? error.details[0].message : null
}
handleSubmit = e => {
e.preventDefault()
const errors = this.validate()
console.log(errors)
this.setState({ errors: errors || {} })
if (errors) return
this.doSubmit()
}
handleChange = ({ currentTarget: input }) => {
const errors = { ...this.state.errors }
const errorMessage = this.validateProperty(input)
if (errorMessage) errors[input.name] = errorMessage
else delete errors[input.name]
const data = { ...this.state.data }
data[input.name] = input.value
this.setState({ data, errors })
}
renderButton = label => {
return (
<button disabled={this.validate()} className="btn btn-primary">
{label}
</button>
)
}
renderInput = (name, label, type = "text") => {
const { data, errors } = this.state
return (
<Input
name={name}
label={label}
error={errors[name]}
type={type}
value={data[name]}
onChange={this.handleChange}
/>
)
}
}
export default Form
loginForm.jsx [Class Component which extends the other]
import Joi from "joi"
import Form from "./common/form"
class LoginForm extends Form {
state = {
data: { username: "", password: "" },
errors: {}
}
schema = {
username: Joi.string().required().label("Username"),
password: Joi.string().required().label("Password")
}
doSubmit = () => {
console.log("Submitted")
}
render() {
return (
<div>
<h1>Login</h1>
<form onSubmit={this.handleSubmit}>
{this.renderInput("username", "Username")}
{this.renderInput("password", "Password", "password")}
{this.renderButton("Login")}
</form>
</div>
)
}
}
export default LoginForm
I already know how to convert a simple Class Component to a Stateless Functional Component but what I don't know is how to convert a Class Component which extends another Class Component.
Please, may you explain me how?
This is not a duplicate question because non of them worked for me and they were doing something different as well.
I have a component of email and password with form validation and now I want to do unit testing, and i want to simulate change on input but i am not able to do it. I have tried both shallow and mount i didn't try render but it wouldn't work either i read it in some documentations. I read somewhere that functions are needed to be binded or something but i am new to testing so i don't know much. This question might be super easy but i have been working on it for hours and i need to get it done. So please guide me and also suggest me if what i am doing is optimal or not.
sign-in.test.jsx
import React from "react";
import { shallow } from "enzyme";
import { BrowserRouter } from "react-router-dom";
import { findByTestAttr } from "../../Utils/testUtils.js";
import SignIn from "./sign-in.component";
const INITIAL_STATE = {
email: "",
password: "",
rememberme: false,
emailErr: "",
passwordErr: "",
buttonErr: "",
progressBar: 0,
disable: true,
};
const setUp = (props = {}) => {
const component = shallow(<SignIn />); // Have also done like this: mount(<BrowserRouter><SignIn /><BrowserRouter />)
return component;
};
//Issue is with the last test case but feel free to suggest me about other tests as well
describe("Sign in component should render ", () => {
let component;
beforeEach(() => {
component = setUp();
});
test("Email input field", () => {
const wrapper = findByTestAttr(component, "email");
expect(wrapper.length).toBe(1);
});
test("It should render password input field", () => {
const wrapper = findByTestAttr(component, "password");
expect(wrapper.length).toBe(1);
});
test("It should render a remember me checkbox", () => {
const wrapper = findByTestAttr(component, "remember-me");
expect(wrapper.length).toBe(1);
});
test("It should render a forget password link", () => {
const wrapper = findByTestAttr(component, "forget-password");
expect(wrapper.length).toBe(1);
});
test("It should render a sign in button", () => {
const wrapper = findByTestAttr(component, "sign-in");
expect(wrapper.length).toBe(1);
});
test("It should render a google sign in button", () => {
const wrapper = findByTestAttr(component, "google-sign-in");
expect(wrapper.length).toBe(1);
});
test("It should render a facebook sign in button", () => {
const wrapper = findByTestAttr(component, "facebook-sign-in");
expect(wrapper.length).toBe(1);
});
});
describe("Form validation with different values", () => {
let component;
beforeEach(() => {
component = setUp();
});
test("Form values", () => {
const input = component.find(".email").at(0);
input.simulate("change", { target: { value: "check" } });
console.log(component.state.email); //undefined
});
});
sign-in.component.jsx
import React from "react";
import { Link } from "react-router-dom";
import CustomButton from "../../components/custom-button/custom-button.component";
import CompanyLogo from "../../components/company-logo-header/company-logo-header.component";
import InputField from "../../components/input-field/input-field.component";
import InputError from "../../components/input-field-error/input-field-error.component";
import { mailFormat, passwordFormat } from "../../Utils/regularExpressions";
import "./sign-in.styles.scss";
const INITIAL_STATE = {
email: "",
password: "",
rememberme: false,
emailErr: "",
passwordErr: "",
buttonErr: "",
progressBar: 0,
disable: true,
};
class SignIn extends React.Component {
constructor() {
super();
this.state = INITIAL_STATE;
}
handleChange = (event) => {
this.setState({
[event.target.name]: event.target.value,
});
const isValid = this.validate();
if (isValid) {
this.setState({ disable: false });
} else {
this.setState({ disable: true });
}
};
validate = () => {
let emailErr = "";
let passwordErr = "";
if (!this.state.email.match(mailFormat)) {
emailErr = "Please enter a valid email format";
}
if (!this.state.password.match(passwordFormat)) {
passwordErr = "Password should be eight digit with letters and numbers";
}
if (emailErr || passwordErr) {
this.setState({
emailErr,
passwordErr,
});
return false;
}
this.setState({
emailErr,
passwordErr,
});
return true;
};
handleSubmit = async (event) => {
event.preventDefault();
if (this.state.disable) {
await this.setState({
buttonErr: "Please enter the email and password",
});
return;
}
const isValid = this.validate();
if (isValid) {
console.log(isValid);
this.setState(INITIAL_STATE);
}
};
render() {
const { disable } = this.state;
return (
<div className="sign-in">
<CompanyLogo />
<form noValidate className="sign-in-form" onSubmit={this.handleSubmit}>
<InputField
name="email"
type="email"
placeholder="Email Address"
data-test="email"
className="email"
onChange={this.handleChange}
value={this.state.email}
/>
<InputError>{this.state.emailErr}</InputError>
<InputField
name="password"
type="password"
placeholder="Password"
data-test="password"
onChange={this.handleChange}
value={this.state.password}
/>
<InputError>{this.state.passwordErr}</InputError>
<div className="remember-forget">
<span className="remember-me">
<input
type="checkbox"
name="rememberme"
value="Remember Me"
data-test="remember-me"
/>
<label htmlFor="rememberme" className="rememberme">
{" "}
Remember me
</label>
</span>
<Link
to="password-reset"
className="forgot-password"
data-test="forget-password"
>
Forgot password?
</Link>
</div>
<div className="center-buttons">
<CustomButton
data-test="sign-in"
type="submit"
SignIn
disabled={disable}
>
Sign In
</CustomButton>
<InputError>{this.state.buttonErr}</InputError>
</div>
<div className="separator">Or</div>
<div className="center-buttons">
<CustomButton data-test="facebook-sign-in" type="button" Options>
Sign in with facebook
</CustomButton>
<CustomButton data-test="google-sign-in" type="button" Options>
Sign in with google
</CustomButton>
</div>
</form>
</div>
);
}
}
export default SignIn;
I learn ReactJs and now I must have Firebase signin. I have a design question on how to detect when Firebase linkWithPopup finish. User press Button and my anonymous user Firebase UID will be turned into a Google credential one.
The linkWithPopup pops up and user select one Google account to use.
I must detect when this process finish or aborted.
Here is my code:
This method get's called when user click Button for Google signin:
onSocialLoginLink = provider => {
const { firebase, changeUserRole } = this.props;
firebase.auth.currentUser
.linkWithPopup(firebase[provider])
// .linkWithRedirect(this.props.firebase[provider])
.then(changeUserRole())
.then(this.fetchSignInMethods)
.catch(error => this.setState({ error }));
};
The problem I encounter is that changeUserRole() gets called before linkWithPopup returns since linkWithPopup of course run asynchronous. This means that my user get this new roll from changeUserRole() even if User select to abort signin.
I must detect when this process finish or aborted.
What would be a recommended best way to do this?
My ide is that if I can detect maybe when signin window looses focus and regain focus I could look at if Firebase user have changed provider to Google or is still anonymous user? Is this doable?
This is the Component that handle signin:
/* eslint-disable max-classes-per-file */
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { compose } from 'recompose';
import { AuthUserContext, withAuthorization } from '../../session';
import { withFirebase } from '../../firebase';
import { SIGN_IN_METHODS } from '../../constants/signinmethods';
import * as ROLES from '../../constants/roles';
import '../../styles/link-account.scss';
import { changeToUserRole } from '../../redux/userData/user.actions';
class LoginManagementBase extends Component {
constructor() {
super();
this.state = {
activeSignInMethods: [],
anonymousSignIn: null,
error: null,
};
}
componentDidMount() {
this.fetchSignInMethods();
}
fetchSignInMethods = () => {
const { firebase, authUser } = this.props;
const email = authUser.email === null ? 'none#guest.ac' : authUser.email;
firebase.auth
.fetchSignInMethodsForEmail(email)
.then(activeSignInMethods =>
this.setState({
activeSignInMethods,
anonymousSignIn: activeSignInMethods.length === 0,
error: null,
}),
)
.catch(error => this.setState({ error }));
};
onSocialLoginLink = provider => {
const { firebase, changeUserRole } = this.props;
firebase.auth.currentUser
.linkWithPopup(firebase[provider])
// .linkWithRedirect(this.props.firebase[provider])
.then(changeUserRole())
.then(this.fetchSignInMethods)
.catch(error => this.setState({ error }));
};
onDefaultLoginLink = password => {
const { firebase, authUser } = this.props;
const credential = firebase.emailAuthProvider.credential(authUser.email, password);
firebase.auth.currentUser
.linkAndRetrieveDataWithCredential(credential)
.then(this.fetchSignInMethods)
.catch(error => this.setState({ error }));
};
onUnlink = providerId => {
const { firebase } = this.props;
firebase.auth.currentUser
.unlink(providerId)
.then(this.fetchSignInMethods)
.catch(error => this.setState({ error }));
};
render() {
const { activeSignInMethods, error } = this.state;
const { saveRolesErr, isSavingRole } = this.props;
// if (isSavingRole) return null;
return (
<div className="provideToggler">
<h1>
You are signed in Anonymously!
<br />
Changes you do is only saved in this browser.
<br /> If you want to access your progress anywhere please sign in below!
</h1>
<ul>
{SIGN_IN_METHODS.map(signInMethod => {
const onlyOneLeft = activeSignInMethods.length === 1;
const isEnabled = activeSignInMethods.includes(signInMethod.id);
return (
<li key={signInMethod.id}>
{signInMethod.id === 'password' ? (
<DefaultLoginToggle
// accountEmail={this.props.authUser.email}
onlyOneLeft={onlyOneLeft}
isEnabled={isEnabled}
signInMethod={signInMethod}
onLink={this.onDefaultLoginLink}
onUnlink={this.onUnlink}
/>
) : (
<SocialLoginToggle
onlyOneLeft={onlyOneLeft}
isEnabled={isEnabled}
signInMethod={signInMethod}
onLink={this.onSocialLoginLink}
onUnlink={this.onUnlink}
/>
)}
</li>
);
})}
</ul>
<h1 style={{ color: 'red' }}>
{error && error.message}
{saveRolesErr && saveRolesErr.message}
</h1>
</div>
);
}
}
const SocialLoginToggle = ({ onlyOneLeft, isEnabled, signInMethod, onLink, onUnlink }) =>
isEnabled ? (
<button type="button" onClick={() => onUnlink(signInMethod.id)} disabled={onlyOneLeft}>
Unlink <i className={signInMethod.icon} aria-hidden="true" /> {signInMethod.name} sign in
</button>
) : (
<button type="button" onClick={() => onLink(signInMethod.provider)}>
Link <i className={signInMethod.icon} aria-hidden="true" /> {signInMethod.name} sign in
</button>
);
// TODO This is not in use but might use it later
class DefaultLoginToggle extends Component {
constructor() {
super();
this.state = { passwordOne: '', passwordTwo: '' };
}
onSubmit = event => {
const { passwordOne } = this.state;
const { onLink } = this.props;
event.preventDefault();
onLink(passwordOne);
this.setState({ passwordOne: '', passwordTwo: '' });
};
onChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
const { signInMethod } = this.props;
const { passwordOne, passwordTwo } = this.state;
const isInvalid = passwordOne !== passwordTwo || passwordOne === '';
return (
<form onSubmit={this.onSubmit}>
Link <i className={signInMethod.icon} aria-hidden="true" /> {signInMethod.name} sign in
<input
name="passwordOne"
value={passwordOne}
onChange={this.onChange}
type="password"
placeholder="Password for email sign in"
/>
<input
name="passwordTwo"
value={passwordTwo}
onChange={this.onChange}
type="password"
placeholder="Confirm New Password"
/>
<button disabled={isInvalid} type="submit">
Save password for email sign in
</button>
</form>
);
}
}
const mapDispatchToProps = dispatch => ({
changeUserRole: () => dispatch(changeToUserRole()),
});
const mapStateToProps = state => {
return {
isSavingRole: state.user.isSavingRoles,
saveRolesErr: state.user.saveRolesErrMsg,
};
};
const enhance = compose(withFirebase, connect(mapStateToProps, mapDispatchToProps));
const LoginManagement = enhance(LoginManagementBase);
const LinkAccounts = () => (
<AuthUserContext.Consumer>
{authUser => (
<div>
<LoginManagement authUser={authUser} />
</div>
)}
</AuthUserContext.Consumer>
);
const condition = authUser => authUser && authUser.roles.includes(ROLES.ANON);
export default withAuthorization(condition)(LinkAccounts);
if that's the problem you can add a condition to check than change the role
const { firebase, changeUserRole } = this.props;
firebase.auth.currentUser
.linkWithPopup(firebase[provider])
.then(res=>{
if(res.credential){changeUserRole()}
})
.then(this.fetchSignInMethods)
.catch(error => this.setState({ error }));
};```
I have used same form to create and update account(module). Create is working fine but in update mode I am not able to set form field value using Set State methods. I have used query component on render methods and setstate not working on rendor method.
import { Mutation } from "react-apollo";
import { Query } from "react-apollo";
import gql from "graphql-tag";
import React, { Component } from "react";
import Router from "next/router";
import Joi from "joi-browser";
const CREATE_ACCOUNT = gql`
mutation CreateAccount(
$name: String
$phone_office: String
$website: String
) {
createAccount(name: $name, phone_office: $phone_office, website:
$website) {
name
phone_office
website
}
}
`;
export const allAccountbyidQuery = gql`
query account($id: String) {
account(id: $id) {
id
name
phone_office
website
}
};
const schema = {
name: Joi.string()
.required()
.error(errors => {
return {
message: "Name is required!"
};
}),
phone_office: Joi.string()
.required()
.error(errors => {
return {
message: "Phone Number is required!"
};
}),
website: Joi.string()
.required()
.error(errors => {
return {
message: "Website is required!"
};
})
};
Main class component
class CreateAccountModule extends React.Component {
static async getInitialProps({ query }) {
const { id } = query;
return { id };
}
constructor(props) {
super();
this.state = {
isFirstRender: true,
name: "",
phone_office: "",
website: ""
};
}
handleChange = event => {
console.log("hello");
const { name, value } = event.target;
this.setState({ [name]: value });
};
validate(name, phone_office, website) {
let errors = "";
const result = Joi.validate(
{
name: name,
phone_office: phone_office,
website: website
},
schema
);
if (result.error) {
errors = result.error.details[0].message;
}
return errors;
}
setName = name => {
if (this.state.isFirstRender) {
this.setState({ name, isFirstRender: false });
}
};
render() {
let input;
const { errors } = this.state;
console.log(this.props);
const allAccountbyidQueryVars = {
id: this.props.id
};
//console.log(allAccountbyidQueryVars);
return (
<Query
query={allAccountbyidQuery}
variables={allAccountbyidQueryVars}
onCompleted={data => this.setName(data.account.name)}
>
{({ data, loading, error }) => {
<CreateAccountModule account={data.account} />;
return (
<Mutation mutation={CREATE_ACCOUNT}>
{(createAccount, { loading, error }) => (
<div>
<form
onSubmit={e => {
e.preventDefault();
const errors = this.validate(
e.target.name.value,
e.target.phone_office.value,
e.target.website.value
);
if (errors) {
this.setState({ errors });
return;
}
if (!errors) {
let accountres = createAccount({
variables: {
name: e.target.name.value,
phone_office: e.target.phone_office.value,
website: e.target.website.value
}
}).then(() => Router.push("/"));
input.value = "";
}
}}
>
{errors && <p>{errors}</p>}
<input
type="text"
name="name"
id="name"
placeholder="Name"
value={this.state.name}
onChange={this.handleChange}
/>
<input
name="phone_office"
id="phone_office"
placeholder="Phone Number"
//value={data.account.phone_office}
//value="123456"
onChange={this.handleChange}
/>
<input
name="website"
id="website"
placeholder="Website"
//value={data.account.website}
onChange={this.handleChange}
/>
<button type="submit">Add Account</button>
<button type="button">Cancel</button>
</form>
{loading && <p>Loading...</p>}
{error && <p>Error :( Please try again</p>}
</div>
)}
</Mutation>
);
}}
</Query>
);
}
}
export default CreateAccountModule;
`
I have tried with props but get props data in apollo state. anyone please suggest possible solution to fix this issue.