Error Handling
Before react 16 javascript error would break the entire app. React 16 provides a built-in solution for handling errors gracefully, with a new lifecycle method called componentDidCatch(). This lifecycle hook gets triggered whenever a component’s render() function throws an error.
With componentDidCatch() comes a new concept of an Error Boundary. Error boundaries are wrapper components that use componentDidCatch() to capture errors anywhere in their child component tree.
For example, when you create an error boundary as a class component:
class ErrorBoundary extends Component { state = { error: false }; componentDidCatch(error, info) { this.setState({ error: true }); } render() { if (this.state.error) { // Fallback UI return <h1>Yikes, something went wrong!</h1> } return this.props.children; } }
You can wrap the error boundary around your entire app, or specific components:
The ErrorBoundary component uses componentDidCatch() to call setState() and display fallback UI when an error occurs anywhere in its child component tree. It can catch errors during rendering, in lifecycle methods, even in the constructor of a child component.
Any errors caught in a component tree get “reported” up to the error boundary’s componentDidCatch(error, info) method where it can be sent to an error reporting service. The method takes two arguments to help you track and investigate errors: error (the error instance) and info (info containing the component stack).
componentDidCatch(error, info) { this.setState({ error: true }); // Log error to error reporting service logError(error, info); }
As we can see, the new componentDidCatch() method works just like a catch {} block for components in React.
It provides a more consistent and dependable way to catch and deal with errors.
Render Arrays, Strings and Numbers
In React 16 we are able to render multiple sibling elements without a wrapping element
by returning an array.This is not possible in previous features. For example, an array of list items:
const JSTeachers = () => { return [ <li key="1">Treasure</li>, <li key="2">Joel</li>, <li key="3">James</li> ]; }
Since you’re returning an array, you should give each element in the array a unique key prop, otherwise React will still display a console warning.
You can render the list items inside the <ul> of another component, alongside other items, and React merges them inside the same list:
const Teachers = () => { return ( <ul> <li>Alena</li> <JSTeachers /> <li>Nick</li> <li>Ben</li> </ul> ); }
Here’s another example of how it can return multiple sibling components via an array:
const App = () => { return [ <Header key="head" />, <Main key="main" />, <Footer key="foot" />, ]; }
Portals
You can insert a child element into a different location in the DOM in react 16.
For example,if you consider an example like in your index.html template,
we’ll usually have a div with the id ‘root’,
which is where our entire app rendered into the DocumentObjectModel via ReactDOM.render():
ReactDOM.render(<App />, document.getElementById('root'));
With the new portals feature, you can add a second element that’s a sibling of your ‘root’ div:
<body> <div id="root"></div> <div id="my-portal"></div> <body>
we can render specific parts of our component tree inside the sibling div via
the new function createPortal(child, container).
<body> <div id="root"></div> <div id="my-portal"></div> <body>return ( ReactDOM.createPortal( <h1>Hello from inside the portal!</h1>, document.getElementById('my-portal') ) );
The function’s first argument (child) is the content you want to render, and the second argument (container) is the DOM element where the content is going to render.
When we need the child to visually ‘break out’ of its container, we use portals and set the setting of parent like
“css as overflow: hidden or as z-index style
We can see portals example when we create modal windows:-
getCourse = course => { const newTitle = course.title; this.setState(state => { if (state.title === newTitle) { return null; } else { return { title: newTitle }; } }); };
class Modal extends Component { render() { return ( ReactDOM.createPortal( this.props.children, document.getElementById('my-portal') ) ); } }
Since Modal returns a portal via createPortal(), you can place it anywhere in your app and it will always render inside the “my-portal” div.
class App extends Component { render() { return ( <div> <header> <h1>Welcome to my App!</h1> </header> <Modal> {/ Modal content /} </Modal> </div> ); } }
Custom DOM Attributes Before React 16, any unrecognized attribute given to an element would be ignored by React. Now, any standard/custom attribute will end up in the DOM. For example, you can provide a custom attribute to a DOM component, example:
<div my-attribute="is-cool">...</div>
React will pass the attribute through to the DocumentObjectModelwhen creating modal windows.
Even though all attributes get rendered to the DOM, you should still use the canonical React naming for known attributes. For example, if you provide class and tabindex to a DOM component, React will warn you about using tabIndex and className instead.
Returning null from setState
React 16 now lets you decide if state gets updated in setState to prevent unnecessary updates.
In our events, we can check if the new value of state is the same as one that is already exists.
It will return null and it won’t re-render the component, if the values are same.
For example:
getCourse = course => { const newTitle = course.title; this.setState(state => { if (state.title === newTitle) { return null; } else { return { title: newTitle }; } }); };
If the values are different, the component re-renders with the new state.
Thanks for reading!