How to continue mounting if condition is met? - reactjs

I am using react and I have componentWillMount which looks like this
componentWillMount() {
axios.get('/user').then(response => {
console.log(response.data.user)
if (response.data.user) {
} else {
this.props.history.replace('/signup');
}
});
}
Notice this line here in the code.
if (response.data.user) {
}
Now, How can I make my container render if the condition is met?

You just need to set the user variable in the component state once you received it in then method, and later you can use it in your render method:
import React from 'react'
class App extends React.Component {
constructor (props) {
super(props)
this.state = { user: null }
}
componentWillMount() {
axios.get('/user').then(response => {
if (response.data.user) {
this.setState({ user: reaponse.data.user )}
} else {
this.props.history.replace('/signup')
}
})
}
render() {
// Do something with the user
if (this.state.user) {
return <div>{this.state.user.name}</div>
}
return <div />
}
}

Hy, render conditionally based on state.
import React from "react";
class ExampleComponent extends React.PureComponent {
state={ user: null }
static getDerivedStateFromProps(nextProps, prevState){
if(!prevState.user && state.user){
this.props.history.replace('/signup');
}
else return null;
}
componentWillMount() {
axios.get('/user').then(response => {
console.log(response.data.user)
if (response.data.user) {
this.setState({ user: response.data.user )}
}
});
}
render() {
const { user } = this.state;
return user ? <div>have user, can return null</div> : <div>loading user</div>
}
}
export default ExampleComponent;

Related

React Native goBack() not being called correctly

My react-native-webview won't go back in any way. Back button press is correctly handled in android and logged in the right way, the WEBVIEW_REF is not null, but even if the "canGoBack" state is true, the webview just won't go back even if able.
I am testing this code in Android
import React, { Component } from "react";
import { BackHandler } from "react-native";
import { WebView } from "react-native-webview";
export default class CustomWebView extends Component {
constructor(props) {
super(props);
this.state = {
canGoBack: false,
}
}
WEBVIEW_REF = React.createRef();
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.handleBackButton);
}
handleBackButton = () => {
if (this.state.canGoBack) {
console.log(this.WEBVIEW_REF.current);
this.WEBVIEW_REF.current.goBack();
}
return true;
}
onNavigationStateChange = (navState) => {
console.log("navState", navState.canGoBack);
this.setState({
canGoBack: navState.canGoBack,
});
};
render() {
return (
<WebView
style={{width:400,height:200}}
source={{
uri: "https://www.google.com/",
}}
ref={this.WEBVIEW_REF}
onNavigationStateChange={this.onNavigationStateChange}
/>
);
}
}
Try like this,
componentDidMount() {
if (Platform.OS === 'android') {
this.backHandler = BackHandler.addEventListener('hardwareBackPress', function () {
return true;
});
}
}
componentWillUnmount() {
this.backHandler.remove();
}

how to use map function with (axios/classhooks) to read from API

import React, { Component } from "react";
import axios from "axios";
class Verifry extends Component {
constructor(props) {
super(props);
this.state = {
s: "0",
user: [],
};
}
/* has title as attribute within the res.data*/
async componentDidMount() {
await axios
.get(http://10.0.0.106:8080/kuwait_elections/api/about_us)
.then((res) => {
const persons = res.data;
this.setState({ user: persons.data.title, s: "4" });
console.log(this.state.user);
});
}
componentDidUpdate() {
// this.state.user.map((u) => {
// return u;
// });
}
render() {
return (
{this.state.user.map((t) => {
return {t.title};
})}
);
}
}
export default Verifry;
Seems your return is not correct. It should be like this.
{
this.state.user.map(({title}) => {
return { title };
})
}
Note: Please format your code properly to make it easier to understand.

Pass array to component

I'm getting a problem trying to send an array that I get from my DB, from a component to another.
I mean, I'm obtaining JSON data and then that data has to be passed to another component.
I was thinking about using the map method.
I checked my console and I noticed that I get the correct data from the DB but when I'm trying to send it by the state, in the class that I want to get the info is null
Class which gets the objects:
import React from 'react'
import { withRouter } from 'react-router-dom'
import MovieList from './MovieList'
import MoviesService from '../services/MoviesService'
class MovieListGet extends React.Component {
constructor (props) {
super(props)
this.state = {
movies: []
}
}
async componentDidMount () {
await this._getMovies()
}
async _getMovies () {
const response = await MoviesService.getMovies()
this.setState({ movies: response.data })
console.log(this.state.movies)
}
async _deleteMovie (id) {
}
_navigateToCreateMovies () {
// Adrress
}
render () {
return (
<div>
<MovieList
movies = {this.state.movies}
onCreateMovie={this._navigateToCreateMovies.bind(this)}
onDelete={this._deleteMovie.bind(this)}
/>
</div>
)
}
}
export default withRouter(MovieListGet)
Class that has to get the array
/* eslint-disable react/prop-types */
import React from 'react'
import {...} from '#material-ui/core'
import { ... } from '#material-ui/icons'
class MovieList extends React.Component {
constructor (props) {
super(props)
const { movies } = props
this.state = {
_movies: []
}
}
componentDidMount () {
console.log(this.props.movie)
this.setState({ _movies: this.props.movies })
}
_renderMovies () {
if (!this.state._movies || this.state._movies.length < 1) {
return (
// Something
)
} else {
return this.state._movies.map(m => (
// something
)
)
}
}
render () {
return (
// Something
)
}
}
export default (MovieList)
MoviesListGet should pass the prop like this:
<MovieList
movies={this.state.movies}
onCreateMovie={this._navigateToCreateMovies.bind(this)}
onDelete={this._deleteMovie.bind(this)}
/>
Then in MoviesList component you can use it like this in you renderMovies method:
class MovieList extends React.Component {
renderMovies () {
if (!this.props.movies || this.props.movies.length < 1) {
return (
// Something
)
} else {
return this.props.movies.map(m => (
// something
)
)
}
}
render () {
return (
// Something
)
}
}
export default MovieList;

LoginPage in React with Redirecting

I have response from server about auth status current user. Based on this information I'm rendering HomePage or LoginPage. How do I can redirect all unauthorized users to '/login' url and others to homepage. When I`m using history.push('/login') it saves permament in url, because in first rendering auth status is always false
import React from 'react';
import './App.scss';
import MainPage from './components/MainPage/MainPage';
import { withRouter, Route } from 'react-router-dom';
import { getAuthStatusThunk } from './redux/authReducer';
import { compose } from 'redux';
import { connect } from 'react-redux';
import Preloader from './components/commons/Preloader/Preloader';
class App extends React.Component {
constructor() {
super()
this.state = { isCheckingLogin: false }
this.getAuthStatusThunk = this.props.getAuthStatusThunk.bind(this)
}
componentDidMount() {
getAuthStatusThunk()
}
async getAuthStatusThunk() {
this.setState({ isCheckingLogin: true })
let res = await (checkIsLoggedIn())
if (res.isLoggedIn) {
this.setState({ isCheckingLogin: false })
}
else {
this.props.history.push('/login')
this.setState({ isCheckingLogin: false })
}
}
render() {
return (
<React.Fragment>
{this.isCheckingLogin ? <Preloader isLoading={true} /> : <MainPage />}
</React.Fragment>
)
}
}
let mapStateToProps = (state) => ({
isAuth: state.authPage.isAuth,
successStatus: state.authPage.successStatus
})
let FunctionRender = compose(
withRouter,
connect(mapStateToProps, { getAuthStatusThunk }))(App)
export default FunctionRender;
You can keep loading and error value also in the state.
Then check if any one of the state value is set or not.
Based on the state value navigate the user accordingly.
You can set a state isCheckingLogin to true while you call the getAuthStatusThunk. Here I include a sample snippet for implementing it.
class App extends React.Component {
constructor() {
super()
this.state = { isCheckingLogin: false }
this.getAuthStatusThunk = this.getAuthStatusThunk.bind(this)
}
componentDidMount() {
getAuthStatusThunk()
}
async getAuthStatusThunk() {
this.setState({ isCheckingLogin: true })
let res = await (checkIsLoggedIn())
if (res.isLoggedIn) {
this.setState({ isCheckingLogin: false })
}
else {
this.props.history.push('/login')
this.setState({ isCheckingLogin: false })
}
}
render() {
return (
<React.Fragment>
{isCheckingLogin ? <Loader /> : <MainPage />}
</React.Fragment>
)
}
}
The Loader component can be used for showing a spinner or some sort of animation while login status is checked if you want.

How to handle event when clicking outside of component?

I reactjs I have a component and it has this code to detect whether there is a click outside the component:
export class Cart extends React.Component {
handleClick(e) {
if (!ReactDOM.findDOMNode(this).contains(e.target)) {
console.log('testing=e.target', e.target)
}
}
componentWillMount() {
document.addEventListener('click', this.handleClick, false);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClick, false);
}
render()
{
return (<div>hello</div>)
}}
However I am getting an error in the findDOMNode statement:
Uncaught Error: Element appears to be neither ReactComponent nor DOMNode
How can I fix this?
You can add id property to the div component, and then refactor the code as follows:
export class Cart extends React.Component {
handleClick(e) {
if (e.target.id === 'div') {
console.log('inside')
} else {
console.log('outside!')
}
}
componentWillMount() {
document.addEventListener('click', this.handleClick, false);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClick, false);
}
render()
{
return (
<div id="div">
hello
</div>)
}
}

Resources