I want to log any errors I am getting to the console and I have been getting this warning when I try to run my tests:
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
in ErrorDialog (at ErrorDialog.test.js:36)
in WrapperComponent
This is what I have for my component:
import React from 'react';
import log from '../pathtologlevel';
import ErrorContext from '../pathtoErrorContext';
class Error extends React.Component {
static type = ErrorContext;
constructor(props, context) {
super(props, context);
this.state = { err: null };
this.processError = this.processError.bind(this);
this.list= [];
}
componentDidMount() {
const errorService = this.context;
errorService.attach((err) => {
log.info('changing state');
this.array.push(err);
this.processError();
});
}
processError() {
const { err } = this.state;
log.info('processNextError', this.array.length, err);
if (!err && this.array.length > 0) {
log.info('Displaying next error');
this.setState({ err: this.array.shift() });
}
}
render() {
const { err } = this.state;
log.info(err);
if (err) {
return this.processError;
}
return null;
}
}
export default Error;
You are returning the function this.processError instead of calling it in the render method. Just call the function this.processError() and you should not be getting any warnings.
Related
constructor(props) {
super(props);
this.state = {
message: ""
};
}
async getData() {
this.setState({...this.state})
await axios.get("https://g...")
.then(function(response) {
console.log(response);
this.setState({message: response.data})
}).bind(this)
}
render() {
return (
<div>
{this.state.message}
</div>
);
}
I tried to use this code to get data from the API. However, the message that is printed out is only linked to the original constructor, and the getData() function does not change the state. How should I go around changing the state after getting data?
You should use componentDidMount, and put the function requesting data in componentDidMount life circle.
By the way, you can add a loading to enhance the user experience : )
import React from 'react';
import "./styles.css";
const BASE_URL = 'https://api.github.com';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ''
}
}
componentDidMount() {
this.getData();
}
async getData() {
try {
const result = await fetch(`${BASE_URL}/repos/facebook/react`);
const toJson = await result.json();
const stringify = JSON.stringify(toJson, null, 2);
this.setState({
message: stringify
})
} catch (error) {
// ignore error.
}
}
render() {
const { message } = this.state;
return (
<div>
{message}
</div>
)
}
}
export default App;
If you are using 'async' and 'await' you don;t have to use then() function
you can write
const data = await axios.get("url")
console.log(data.data)
this.setState({message:data.data})
im upgrading an old react pp to use functional components. I am having troubles with the error boundary class component . I simply dont understand how to update the static getDerivedStateFromError what is the correct syntax to update this function?
initial component
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = {
hasError: false,
};
}
static getDerivedStateFromError(_error) {
return { hasError: true };
}
componentDidCatch(error, info) {
sendError("ErrorBoundary", { info }, error);
}
render() {
if (this.state.hasError) {
return <ErrorText />;
} else {
return this.props.children;
}
}
}
New component, which is imssing something for sure as it never sets the error to true, which was done by the static function..
const ErrorBoundary = (props) => {
const [hasError, setHasError] = useState(false)
try {
if (hasError) {
return <ErrorText />;
} else {
return props.children;
}
} catch {
sendError("ErrorBoundary", { info }, error);
}
}
There's no way to do the componentDidCatch nor the getDerivedStateFromError on hooks right now. Here's the documentation:
https://reactjs.org/docs/hooks-faq.html#from-classes-to-hooks
getSnapshotBeforeUpdate, componentDidCatch and getDerivedStateFromError: There are no Hook equivalents for these methods yet, but they will be added soon.
The code below was supposed to return my application private and public keys. When I run the code, only the private keys gets alerted and successfully.
The publickey throws error
TypeError: u.getPublickKeyFromPrivate is not a function
import React, { Component } from 'react';
import {
ProfileData
} from 'bacoma';
const bacoma = require( 'bacoma' );
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
},
publicKey: "",
};
}
componentDidMount() {
this.recordedData();
}
componentWillMount() {
const { userSession } = this.props;
this.setState({
});
}
recordedData() {
const { userSession } = this.props
var appkeyPrivate = userSession.appPrivateKey;
alert('am privatekey: ' +appkeyPrivate);
var publicKey = bacoma.getPublickKeyFromPrivate(appkeyPrivate);
alert('am pubick key: ' +publicKey);
console.log('iam publick key: ' +publicKey);
}
render() {
const {userSession } = this.props;
return (
// returned content here
);
}
}
Any idea on what could be the problem
Resolved by appending userSession to the properties
var publicKey = userSession.getPublickKeyFromPrivate(appkeyPrivate);
I have a component wrapped in an Error Boundary, when a button is clicked a validate() function is called, this function throws an error if there is not information provided however the ErrorBoundary is not catching this error.
Render function on Component
return (
<ErrorBoundary>
...
<Playlist
...
onClick={this.addPlaylistToSpotify} // this function can throw an error
...
/>
</ErrorBoundary>
);
Function with error
addPlaylistToSpotify = () => {
try {
addPlaylist(this.state.newPlaylist); // this function throws an error on validate()
} catch (error) {
throw new Error(error);
}
...
};
ErrorBoundary Component
import React, { Component } from "react";
import { ErrorOverlay } from "../../components/index";
import styles from "./ErrorBoundary.css";
export class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = {
hasError: false,
error: null,
errorInfo: ""
};
}
componentDidCatch(error, errorInfo) {
this.setState({
hasError: true,
error: error,
errorInfo: errorInfo
});
// TODO: log the error somewhere in the db
}
dismiss() {
this.setState({
hasError: false,
error: null,
errorInfo: ""
});
}
render() {
if (this.state.hasError) {
return (
<ErrorOverlay message={this.state.errorInfo} dismiss={this.dismiss} />
);
} else {
return this.props.children;
}
}
}
Any help would be hugely appreciated, thanks!
Any help would be hugely appreciated. Thanks!
From React docs
https://reactjs.org/docs/error-boundaries.html#how-about-event-handlers
Note
Error boundaries do not catch errors for:
Event handlers
Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)
Server-side rendering
Errors thrown in the error boundary itself (rather than its children)
In your code, the error is thrown from an event handler (addPlaylistToSpotify) so componentDidCatch can't catch the error. Therefore you need to do something like this:
import React from 'react';
export class Playlist extends React.Component {
constructor (props) {
super(props);
this.state = {
error: false
// ...
}
}
addPlaylistToSpotify = () => {
try {
// Something throws an error here.
} catch (error) {
this.setState({ error: true });
}
}
render() {
if (this.state.error) {
throw new Error('I crashed!');
}
return (
<div>
...
<button onClick={this.addPlaylistToSpotify}>Add song</button>
...
</div>
)
}
}
I hope this helps.
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;