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>)
}
}
Related
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();
}
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.
I want to pass down a function isLoggedIn to child component HandleArticle as a prop.
Even though I am using arrow function due to this issue, TypeError: this.isLoggedIn is not a function occurs.
class HandleNews extends React.Component {
isLoggedIn = () => {
if (!this.props.isSignedIn) {
history.push("/");
} else {
return <div>hello</div>;
}
};
render() {
return (
<div>
<Link to="/news/article">
<HandleArticle isLoggedIn={this.isLoggedIn} />
</Link>
</div>
);
}
}
const mapStateToProps = state => {
console.log(state);
return {
isSignedIn: state.auth.isSignedIn
};
};
export default connect(mapStateToProps)(HandleNews);
As per the documentation, the arrow syntax is still in proposal stage for passing functions.
isLoggedIn = () => {
if (!this.props.isSignedIn) {
history.push("/");
} else {
return <div>hello</div>;
}
};
Use bind syntax in constructor for isLoggedIn function
this.isLoggedIn = this.isLoggedIn .bind(this);
Bind directly in render function
<HandleArticle isLoggedIn={this.isLoggedIn.bind(this)} />
I searched for error handling in react.
and i found componentDidCatch.
but componentDidCatch only catch in render.
I want to catch a error in method.
My source
import React from 'react';
class Child extends React.Component{
handleError = () => {
throw new Error('Error');
}
render() {
return (
<button onClick={this.handleError}>Error</button>
);
}
}
export default Main extends React.Component {
componentDidCatch(error,info) {
console.log(error, info); // NOT WORK
}
render() {
return (<Child/>);
}
}
You can check official React's Error handeling page where they use this code:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
// Display fallback UI
this.setState({ hasError: true });
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
this codebox that is official Dan Abramov's (creator of React) CodeBox: https://codepen.io/gaearon/pen/wqvxGa?editors=0010
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;