Proper way to show loading state before show DOM in React - reactjs

I just want to know, what is the best way to show loading state before data that is being fetched by AJAX loaded. I've tried to reproduce it using setInterval on codepen. Code
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isFetching: true,
};
}
componentWillMount() {
let that = this;
setTimeout(function() {
that.setState({
isFetching: false,
});
}, 2000);
}
render() {
return (
<div>
{this.state.isFetching ? 'Fetching' : 'Done'}
</div>
);
}
}
React.render( <App / > , document.getElementById('root'));

Related

React Hooks in class using timeout

I am quite new in React... I have page where window is showing with little delay..
it is made with Hooks:
export default function LoginPage() {
const [cardAnimaton, setCardAnimation] = React.useState('cardHidden');
setTimeout(function() {
setCardAnimation('');
}, 700);
<form>
<Card login className={classes[cardAnimaton]}>
Now I want to use classes in that page and I want to preserve the same effect..
So I am trying something like:
export default class LoginPage extends React.Component {
constructor(props) {
super(props);
this.state = {
cardHidden: true,
};
}
componentDidMount() {
this.timeout = setTimeout(() => {
this.setCardAnimation('');
}, 700);
}
setCardAnimation = () => {
this.cardAnimaton({ cardHidden: false });
};
I have no idea... got stuck there...
You just need to set your cardHidden: false inside componentDidMount and then you can add animation based on cardHidden state.
here is a working Demo which I used cardHidden state to show or hide different text on screen which you can use this method for adding different animation.
just click Run code snippet to see how it works
class LoginPage extends React.Component {
constructor(props) {
super(props);
this.state = {
cardHidden: true,
};
}
componentDidMount() {
this.timeout = setTimeout(() => {
this.setState({
cardHidden: false
});
}, 700);
}
render() {
if(this.state.cardHidden){
return <div>I'm Hidden</div>
} else {
return <div>Haha, I'm Visible</div>
}
}
}
const rootDiv = document.getElementById('root');
ReactDOM.render(<LoginPage />, rootDiv);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
In class-based component, you need to use this.setState to update the state.
export default class LoginPage extends React.Component {
constructor(props) {
super(props);
this.state = {
cardHidden: true,
};
}
componentDidMount() {
this.timeout = setTimeout(() => {
this.setState({ cardHidden: false });
}, 700);
}
...
check https://reactjs.org/docs/react-component.html#setstate

React: Issues with Conditional Rendering

In my React-App, i use the Firebase SDK. If a user wants to reset his password, he will be redirected to a page within my app. If the code is valid, the component <PWResetConfirmForm /> should be rended. If the code is invalid, the component <PWResetOutdatedForm /> is to be rendered.
My Page Component looks like this:
class PWResetConfirmPage extends Component {
constructor(props) {
super(props);
this.state = {};
this.verfiyResetPassword = this.verfiyResetPassword.bind(this);
}
verfiyResetPassword() {
const params = (new URL(`http://dummy.com${this.props.location.search}`)).searchParams;
const code = params.get("oobCode")
auth.doVerfiyPasswordReset(code)
.then(function () {
return (
<div className="HomePage-Main">
<TopBar></TopBar>
<PWResetConfirmForm></PWResetConfirmForm>
</div>
);
})
.catch(function () {
return (
<div className="HomePage-Main">
<TopBar></TopBar>
<PWResetOutdatedForm></PWResetOutdatedForm>
</div>
);
})
}
render() {
return (
<div>
{this.verfiyResetPassword()}
</div>
);
}
}
export default PWResetConfirmPage
When i try to run, i get a blank page and not error.
Where is my issue and how can i fix that?
Thank you very much for your help and for your time
You will not be able to return JSX from within then()/catch() of auth.doVerfiyPasswordReset() like that. You can instead approach this by taking advantage of React.Component lifecycle method componentDidMount and using setState() to manipulate state properties for conditional rendering. I've added state properties to the component, one to track whether loading (API call has completed) and one to track whether the call was a success (then) or failure (catch). These properties are used to conditionally generate JSX content for rendering. This is assuming that verfiyResetPassword() is intended to run when the component is first mounted, instead of every time render() is called:
class App extends Component {
constructor() {
super();
this.state = {
isResetVerified: null,
loading: true
};
}
componentDidMount() {
this.verfiyResetPassword();
}
verfiyResetPassword() {
const params = (new URL(`http://dummy.com${this.props.location.search}`)).searchParams;
const code = params.get("oobCode")
auth.doVerfiyPasswordReset('foobar')
.then(() => {
this.setState({
...this.state,
isResetVerified: true,
loading: false
});
})
.catch(() => {
this.setState({
...this.state,
isResetVerified: false,
loading: false
});
})
}
getContent() {
if (this.state.loading) {
return (
<div>Loading...</div>
);
} else {
if (this.state.isResetVerified) {
return (
<div className="HomePage-Main">
<TopBar></TopBar>
<PWResetConfirmForm></PWResetConfirmForm>
</div>
);
} else {
return (
<div className="HomePage-Main">
<TopBar></TopBar>
<PWResetOutdatedForm></PWResetOutdatedForm>
</div>
);
}
}
}
Here is a basic example in action.
Also, in the constructor this.verfiyResetPassword = this.verfiyResetPassword.bind(this); would only be needed if verfiyResetPassword() is executed by a DOM event such as button onClick or similar.
Hopefully that helps!
I could still fix the error myself:
class PWResetConfirmPage extends Component {
constructor(props) {
super(props);
this.state = {
isValid: false,
code: "",
};
this.verfiyResetPassword = this.verfiyResetPassword.bind(this);
}
componentDidMount() {
const params = (new URL(`http://dummy.com${this.props.location.search}`)).searchParams;
const code = params.get("oobCode")
this.setState({code:code})
auth.doVerfiyPasswordReset(code)
.then(() => {
this.setState({
...this.state,
isValid: true,
});
})
.catch(() => {
this.setState({
...this.state,
isValid: false,
});
})
}
verfiyResetPassword() {
if (this.state.isValid) {
return (
<div>
<TopBar></TopBar>
<PWResetConfirmForm code={this.state.code}></PWResetConfirmForm>
</div>
);
} else {
return (
<div>
<TopBar></TopBar>
<PWResetOutdatedForm></PWResetOutdatedForm>
</div>
);
}
}
render() {
return (
<div className="HomePage-Main">
{this.verfiyResetPassword()}
</div>
);
}
}
export default PWResetConfirmPage

React: TypeError: this._modal.$el.on is not a function

So I'm new to react and I'm trying to use a boilerplate but I'm getting the following error in the chrome console. Sorry if this is a repeat question but I've tried to google it and found nothing. Thanks for the help in advance.
(Console)
TypeError: this._modal.$el.on is not a function
(index.js)
import React from 'react'
import UIkit from 'uikit'
export default class Modal extends React.Component {
constructor(props) {
super(props)
}
componentDidMount() {
this._modal = UIkit.modal(this.refs.modal, {
container: false,
center: true
// stack: true
})
console.log(this._modal)
this._modal.$el.on('hide', () => {
this.props.onHide()
})
this._modal._callReady()
if(this.props.visible) {
this._modal.show()
}
}
componentWillReceiveProps(nextProps) {
const { visible } = nextProps
if(this.props.visible !== visible) {
if(visible) {
this._modal.show()
} else {
this._modal.hide()
}
}
}
render() {
return (
<div ref="modal">
{this.props.children}
</div>
)
}
}
It is recommended to handle your modal with your compoenent state and refs are usually used for DOM manipulation.
What you can do is to initialize your state:
constructor(props) {
super(props)
this.state= {
isOpen : false
}
}
in your componentWillReceiveProps:
componentWillReceiveProps(nextProps) {
const { visible } = nextProps
if(this.props.visible !== visible) {
this.setState({
isOpen: visible
})
}
}
and in your render method:
render() {
return (
<div ref="modal">
{this.state.isOpen && this.props.children}
</div>
)
}
Let me know if this issue still persists. Happy to help

setState inside constructor not working properly: ReactJS

I'm trying to run the below code in React+Redux but am running into an unhandled
exception 'NodeInvocationException: Cannot read property 'showText' of
null TypeError: Cannot read property 'showText' of null'
import * as React from 'react';
import { NavMenu } from './NavMenu';
import { Component } from 'react';
export interface BlinkState
{
showText: boolean;
text: '';
}
type BlinkProps = BlinkState;
class Blink extends React.Component<BlinkProps, BlinkState> {
constructor(props: BlinkProps) {
super(props);
//this.state = { showText: true };
this.setState({ showText: true, text: props.text });
// Toggle the state every second
setInterval(() => {
this.setState(previousState => {
return { showText: !previousState.showText };
});
}, 1000);
}
render() {
let display = this.state.showText ? this.props.text : ' ';
return <div>{ display }</div>;
}
}
export class Layout extends React.Component<{}, {}> {
public render() {
return <div className='container-fluid'>
<Blink showText=false text='I love to blink' />
</div>;
}
}
I'm just trying to figure out how to render the Blink copmonent with the props passed in...
You missed the basic thing, use of constructor and setState, use of constructor is to initialize the state value and use of setState is to update the state value, so using setState inside `constructor doesn't makes any sense.
Better way will be, initialise the state in constructor and to run the time use componentDidMount lifecycle method, also don't forgot to stop the time before unmounting the component, to clear it use componentWillUnmount lifecycle method.
Write the component like this:
class Blink extends React.Component<BlinkProps, BlinkState> {
constructor(props: BlinkProps) {
super(props);
this.state = { showText: false };
}
componentDidMount(){
this.timer = setInterval(() => {
this.setState(previousState => {
return { showText: !previousState.showText };
});
}, 1000);
}
componentWillUnmount(){
clearInterval(this.timer)
}
render() {
let display = this.state.showText ? this.props.text : ' ';
return <div>{ display }</div>;
}
}
Working code:
class Blink extends React.Component {
constructor(props) {
super(props);
this.state = { showText: true, text: props.text };
}
componentDidMount(){
this.timer = setInterval(() => {
this.setState(prev => {
return { showText: !prev.showText };
});
}, 1000);
}
componentWillUnmount(){
clearTimer(this.timer)
}
render() {
let display = this.state.showText ? this.props.text : ' ';
return <div>Hello { display }</div>;
}
}
class Layout extends React.Component{
render() {
return <div className='container-fluid'>
<Blink text='I love to blink' />
</div>;
}
}
ReactDOM.render(<Layout/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'/>
You should not specify actions to be taken in the constructor or use setState there, constructor should be used to simply set an initial state.
Also you might need to update the state text since its being set based on props. Do it in the componentWillReceiveProps.
Also when you are using setInterval, make sure to clearInterval when the componentUnmounts
constructor(props: BlinkProps) {
super(props);
this.state = { showText: true, text: props.text };
}
componentWillReceiveProps(nextProps) {
this.setState({text: nextProps.text});
}
componentDidMount() {
// Toggle the state every second
this.interval = setInterval(() => {
this.setState(previousState => {
return { showText: !previousState.showText };
});
}, 1000);
}
componentWillUnmount() {
clearInterval(this.interval)
}

blinking text with React using state and setTimeOut

I am trying to show blinking text using react:
class BlinkLable extends React.Component {
constructor(props) {
super(props);
this.state = {showlabel: true,
label: this.props.label
};
this.myFunction = this.myFunction.bind(this);
}
myFunction()
{
var sLb = ! (this.state.showlabel);
this.setState({showlabel: sLb});
}
componentDidMount() {
setTimeout(this.myFunction, 3000)
}
render() {
return (
<div>
{(this.state.showlabel)?this.state.label:''}
</div>
);
}
}
ReactDOM.render(
<BlinkLable label='MY MESSAGE'/>,
document.getElementById('labelId')
);
However, after it shows MY MESSAGE, this message dissapears and never comes back. What could be the problem?
You need to use setInterval() method.
componentDidMount() {
setInterval(this.myFunction, 3000)
}
More Info: 'setInterval' vs 'setTimeout'
Modify this function to:
myFunction()
{
this.setState((prevState) => {
return {
showlabel: !prevState.showLabel
}
});
}
class BlinkLable extends React.Component {
constructor(props) {
super(props);
this.state = {showlabel: true,
label: this.props.label
};
this.myFunction = this.myFunction.bind(this);
}
myFunction(){
var sLb = ! (this.state.showlabel);
this.setState({showlabel: sLb});
}
render(){
return (
<div>
{(this.state.showlabel)?this.state.label:''}
</div>
);
}
componentDidUpdate() {
setTimeout(this.myFunction, 2000)
}
componentDidMount(){
setTimeout(this.myFunction, 2000)
}
}
ReactDOM.render(
<BlinkLable label='MY MESSAGE'/>,
document.getElementById('labelId')
);
<div id="labelId"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
you need to know react's component life cycle.
componentDidMount() is called only when a component is mounted.
componentDidMount() is invoked immediately after a component is
mounted. Initialization that requires DOM nodes should go here.
Therefore if you want to keep blinking, add componentDidUpdate().

Resources