Check state from imported component - reactjs

Much of a basic question. Can I pass the state property to another component? So if I create a login app and after a successful login from API call I set the state of loggedInUser: 12345 in say a component called Login.js
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
data:[],
loggedInUser: 12345
}
}
render(){
return(
//Return the this.state.loggedInUser
)
}
}
How can I pass this.state.loggedInUser from Login.js to another component where I've imported Login.js?
For example, in my Page1.js I have import Login from './Login'
Can something like this be achieved? I just want to pass the this.state.loggedInUser value to any page where it us imported.
Thanks.

As mentioned in the comment above, redux is probably best practice here. But here is an example of accomplishing this with vanilla react.
export default class Parent extends Component {
constructor(props) {
super(props)
this.state = {
logginUser: undefined
}
this.handleUserState = this.handleUserState.bind(this);
}
handleUserState = (userInfo) => {
this.setState({logginUser: userInfo})
}
render = () => {
return (
<div>
<Login handleUserState={this.handleUserState} />
</div>
)
}
}
export default class Login extends Component {
constructor(props) {
super(props);
this.loginUser = this.loginUser.bind(this);
}
loginUser = (e) => {
e.preventDefault()
<--- make call to api for userInfo here and pass it to the call below --->
this.props.handleUserState(userInfo)
}
render =() => {
return(
<div>
<button type="submit" onClick={this.loginUser} />
</div>
)
}
}
Basically what's happening here since you are importing Login into another component, you will have that 'Parent' component act as the state manager and save the user data at that level. You then pass the function that updates the state to the Login component and call it once you have the user data to update it with.
I hope this helps!

Related

Update state from other Component to Main Component

I created a component/file in my React-Project, so that I can better organize it.
I have exported a Login-Component <SignInSide></SignInSide> and imported it in my main file:
Main-File:
export default class Login extends Component {
constructor(props) {
super(props);
this.onChangeUsername = this.onChangeUsername.bind(this);
this.state = {
username: ""
};
}
onChangeUsername(e) {
this.setState({
username: e.target.value
});
}
render() {
return (
<SignInSide></SignInSide>
);
}
}
This is my very basic Login-Component. As I already said, I just want to call this.onChangeUsernam when I imported this as <SignInSide></SignInSide> but i dont know what I have to write inside the onClick-Argument inside of the Login-Component to get/update the state from the Main-File.
Login-Component
export default function SignInSide(props) {
return (
<form className={classes.form}>
<TextField/>
<Button>
Login
</Button>
</form>
);
}
I am very thankful for helping. Can you give me a short and easy to understand example, so that I can add this by myself to my project? I only have to understand, what i have to do.
To update the Login component's state, you need to pass props from parent component to child component (passing props from Login to SignInSide component).
Therefore, you need to pass onChangeUsername method as a prop to the <SignInSide/> component. Inside SignInSide component, you need to manage a local state to keep the text input that you entered. It only needs to be used when you're submitting the data which trigger the onClick function onChangeUsername which has been passed from parent component.
Main-File:
import { Component } from "react";
import SignInSide from "./SignInSide";
export default class Login extends Component {
constructor(props) {
super(props);
this.onChangeUsername = this.onChangeUsername.bind(this);
this.state = {
username: "",
};
}
onChangeUsername(data) {
this.setState({
username: data,
});
}
render() {
console.log("username updated: ", this.state.username);
return <SignInSide onChangeUsername={this.onChangeUsername} />;
}
}
SignInSide Component:
import { useState } from "react";
export default function SignInSide(props) {
const [data, setData] = useState("");
const handleChange = (e) => setData(e.target.value);
return (
<form>
<label>
User Name:
<input type="text" value={data} onChange={handleChange} />
</label>
<button type="button" onClick={() => props.onChangeUsername(data)}>
Submit
</button>
</form>
);
}
Application View
Check the console logs as shown in the application view to identify whether username is updated in main component.

How can I obtain class props from url and store in react-redux

so I am trying to pass params using route to a react component and also at the same time use Component class props. Here is what am doing
import { loadSchemes, } from '../../actions/schemes;
export class Schemes extends Component {
constructor(props) {
super(props);
const { match: { params } } = this.props;
this.state = {
client_id: params.pk,
}
}
componentDidMount() {
this.props.loadSchemes();
}
render(){
return(
<div>
{this.props.schemes_list.map((scheme,index)=><p key={index}>{scheme}</p>)}
</div>
)
}
}
const mapStateToProps = (state) => ({
schemes_list: state.schemes,
});
export default connect(mapStateToProps,{ loadSchemes,})(Schemes);
And I have a url to this component as
<Route path="/client/:pk/schemes" component={Schemes}/>
The problem is I get an error this.props.schemes_list is undefined and this.props.loadSchemes is undefined
please help am using react-redux
Obviousely in component from where you call Scheme, you import { Schemes }, an unconnected component, instead of Schemes - default connected component. Please check it.

Update parent component State from child component in react js

I am setting a state into child component on event perform and want to sent this to Parent component. I searched for this on SO. But still didn't found any way to do this.
Let say i have a parent component Home, and have child component User. I am performing some event in User component, and at that time, i want to pass data to Home component. How can i do this?
Below is my code:
/* Parent component */
import React, { Component } from 'react';
import User from './user';
class Home extends React.Component{
constructor(props){
super(props)
this.state = {
isReportSent: false
}
}
render(){
<Switch>
<Route exact path="/" component={User}/>
</Switch>
}
}
/* child component */
class User extends React.Component{
constructor(props){
super(props)
}
render(){
}
}
Note: My parent component is Routing component, in which i am routing my child component on particular path. So can't pass any function to child component.
import React, { Component } from "react";
class Home extends Component {
constructor(props) {
super(props);
this.state = {};
}
onChildAPICall = result => {
console.log(result);
};
render() {
return <User onAPICall={this.onChildAPICall} />;
}
}
class User extends Component {
constructor(props) {
super(props);
this.state = {};
this.API = "https://apicall";
}
makeAnAPICall = async () => {
let result = await fetch(this.API);
this.props.onAPICall(result);
};
render() {
return <button onClick={this.makeAnAPICall}>API Call</button>;
}
}
export default Home;
Something like this would work. I'm not sure if the below is 100% functioning as I just wrote it quickly but the idea is to pass down setState() as a prop from parent to child. So when child calls setState from props it's setting state in the parent component.
class Home extends React.Component {
constructor (props) {
super(props)
this.state = {
data: []
}
}
render () {
<ChilComponent setState={this.setState} />
}
}
const User = async ({ setState }) => {
const receivedData = await getDataHowever(params)
setState({
data: receivedData
})
return (
<p>Got data!</p>
)
}
You can call callback function of parent from child component and in parent you can set the state based on callback response.
import React, { Component } from "react";
class Home extends Component {
constructor(props) {
super(props);
this.state = { }
}
setStateOfParent= result => {
this.setState({result : result});
}
render() {
return <User setStateOfParent={this.setStateOfParent} />;
}
}
class User extends Component {
constructor(props) {
super(props);
this.state = {};
this.API = "https://apicall";
}
makeAnAPICall = async () => {
let result = await fetch(this.API);
this.props.setStateOfParent(result);
};
render() {
return <button onClick={this.makeAnAPICall}>API Call</button>;
}
}
export default Home;
Your explanation is not all clear what you want to acheive but as a simple pattern you can pass the callback prop to the child component using render method of react router
Parent Component
<Route exact path="/" render={(props) => <User {...props} callback={this.callback} />}/>
Child Class
this.props.callback(data)
#user10742206 The best way is to create an independent component and include it as a child in any parent component. Then you can pass a callback function from parent and child can use it to send back any data to parent.

Can I set state of imported component in react native?

I want to set state of imported component. Something like
import ProductListing from '../components/ProductListing';
constructor(props){
super(props);
ProductListing = new ProductListing();
ProductListing.state = {someVariable : 'hello'};
}
Send data as props from the component where you want to use and inside the state of that component use it.
Example:
import UserInfo from './userInfo.js'
class UserDetail extends React.Component {
render()
{
return(
<UserInfo myNewState= {//define your state here} />
)
}
}
And inside UserInfo use this:
....
state= {this.props.myNewState}
If your aim is just to update the state of the child component in your case it is ProductListing. So you can do these steps
Create ProductListing as a react class so that you can create a reference for that
class ProductListing extends Component (){
state = {
items: []
}
updateStateItems = (data) => {
this.setState({ items: data })
}
render() {
return(
// your render method code code
)
}}
import ProductListing in your parent class and create a reference for that and in componentDidMount using the reference call functionupdateStateItems with data that you want to set in ProductListing state.
import ProductListing from './ProductListing'
class ParentClass extends Component (){
constructor(props){
super(props)
}
componentDidMount(){
// here use that reference to pass the data that you want to set in state
this.ref.updateStateItems(data)}
render() {
return(
<div>
<ProductListing
// to create a reference of product listing
ref={(ref) => { this.ref = ref }}
/>
</div>
)
}}

React material UI open login dialog if token expired

I am using react material UI. I am frequently checking if token is expired using setInternval() and if its expire than login dialog should be open and setInterval should be cleared using clearInterval(). Below is my code but I am getting warning as Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. and not able to achieve the required result.
App.js
import AuthService from './includes/AuthService.js';
class App extends React.Component {
constructor(props) {
super(props);
this.Auth = new AuthService();
}
componentDidMount(){
setInterval(() => {this.Auth.checkToken()}, 10000);
}
}
AuthService.js
class AuthService extends React.Component{
constructor(props) {
super(props);
this.state = {email: '', password : '', loginOpen : false};
}
checkToken() {
console.log("token checked");
if (decode(localStorage.getItem('jwtToken')).exp < Date.now() / 1000) {
this.setState({loginOpen : true}, () => {
console.log('state updated');
console.log(this.state.loginOpen);
clearInterval();
});
}
}
render(){
const { onRequestClose } = this.props;
const actions = [
<FlatButton
label="Close"
primary={true}
onClick={this.handleClose}
/>,
];
return (
<MuiThemeProvider>
<Dialog title="Result Details"
actions={actions}
modal={false}
open={this.state.loginOpen}
onRequestClose={this.handleClose}
autoScrollBodyContent={true}
>
</Dialog>
</MuiThemeProvider>
}
loginOpen and checkToken() look like something that can be moved up to App component, and be passed to AuthService as props.
Alternatively, you can simply move down and call checkToken() on componentDidMount() function of AuthService.
Like this:
class AuthService extends React.Component{
constructor(props) {
super(props);
// ...
this.checkToken = this.checkToken.bind(this);
this.intervalId = null;
}
componentDidMount(){
this.intervalId = setInterval(() => {this.checkToken()}, 10000);
}
checkToken() {
console.log("token checked");
if (decode(localStorage.getItem('jwtToken')).exp < Date.now() / 1000) {
this.setState({loginOpen : true}, () => {
console.log('state updated');
console.log(this.state.loginOpen);
if (this.itv) {
clearInterval(this.intervalId);
}
});
}
}
See which approach will work better, and see if my fix works, and I can add more explanations.
One more thing I want to point out is that clearInterval(..) takes the ID returned from setInterval.
Hence the setting of this.intervalId and passing it to clearInterval(..).
From your comment:
how can I change state in parent component i.e. app component from its
child component. Becase login modal is in app component.
You are rendering login modal in App component.
You can conditionally render the login modal based on App's this.state.loginOpen.
For example, if your App render function contains a login modal component called LoginModal
render() {
<div>
{ this.state.loginOpen && <LoginModal /> }
</div>
Or, if you are calling some function to show the login modal, you can do something like if (this.state.loginOpen) { showLoginModal(); }.

Resources