App Component is Getting Props Magically? - reactjs

I'm checking the code base of a functioning react web-app, and struggling to understand the following from the App.js file:
class App extends React.Component {
render() {
let error = null
if (this.props.error) {
error = <ErrorMessage
message={this.props.error.message}
debug={this.props.error.debug} />
}
return (
<Router>
{this.props.isAuthenticated ?
<div className="holder">
<NavBar
isAuthenticated={this.props.isAuthenticated}
...
Specifically, where does props (this.props.error and this.props.isAuthenticated) come from? Seems like it isn't defined anywhere. In Index.js, it renders the App component without passing in any props ReactDOM.render(<App />, document.getElementById('root'));.
Edit: at the bottom of App.js, it's exported with export default withAuthProvider(App)
and there's a file called AuthProvider.tsx which defines error and isAuthenticated.

Well withAuthProvider is a Higher-Order component. You can learn more about this pattern here. They're actually functions that take a React component as an argument (App in this case) and enhance it with props or logic. withAuthProvider wraps the App component and provides it the error and isAuthenticated props, while it could also implement some authentication logic for you.

Related

How to wrap ALL components of react in a HOC?

ReactJS is a great library, However, it misses some features which I found in Vue and Angular. These features can be implemented of course in React, however, they require extra code to be written.
Every react component, or every JSX element I should say has the following properties shared, which are given by React to us to consume:
ref
key
I wanted to add extra props:
renderIf
fallback
These props help in a way I can't describe when it comes to conditional rendering and filtering the views based on the logged-in user permissions and roles (and other conditional rendering use cases, of course).
In react, if we wanted to apply these props to our components, we would use a HOC as follows:
// 🍎 Disclaimer: you don't have to understand any of the code written bellow, the general idea is that this is a HOC.
import React from 'react'
import getVal from './getVal'
export default function EnhancedComponent(OriginalComponent) {
return ({ renderIf: renderIf_ = true, override: override_, fallback: fallback_ = undefined, ...props }) => {
const renderIf = getVal(renderIf_)
const override = getVal(override_)
const fallback = getVal(fallback_)
const consumersComponent = <OriginalComponent {...props} />
let render = fallback
if (renderIf) render = consumersComponent
if (override_ !== undefined) render = override
return render
}
}
Where every time you want to apply these props to your components, you would have to wrap every new component you create with EnhancedComponent as follows:
export default EnhancedComponent(function Sidenav(){
return <div> side nav </div>
})
Now, you can use your Sidenav component within your App component as follows:
import Sidenav from './Sidenav'
export default function App(){
return (
<div>
<Sidenav renderIf={(5 + 5 === 10)}/>
<div>etc</div>
</div>
)
}
This API is great, but it has a drawback, which is, every time you want to apply these cool props (renderIf and fallback) you'll have to repeat these steps:
import Enhanced component to your file.
wrap your export with Enhanced component.
What I am looking for, is a method, or a way to inherit, or to add some props to the original react component class, somehow?
In react class components, I can imagine doing this on the React.Component class which we used to extend from in the past
class Car extends React.Component{
constructor(){}
render(){
return <div>I miss you 🌹</div>
}
}
But in react functional component, how can we do that?
I want to apply these props by default everytime I create a new component, without wrapping my components in a HOC everytime.
Does React have a way to do that? To change its defaults ?

React app does not have consistent provider for redux in children

I am building a React app with sagas for Redux and next.js. The main app.js file is handled as follows:
import { wrapper } from '../state/store';
const App = ({ Component, pageProps }) => (
<Layout>
<Component {...pageProps} />
</Layout>
);
export default wrapper.withRedux(App);
I can call and write to the state using dispatch for the pages in this app and some of their direct children. However, with others I get an error that is always something like ...
Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider>
I don't understand how the parent page and some children are fine, but others have problems. It seems like components must be registered somewhere to be in the provider as every new component that I add has problems.
If the app is not wrapped in a provider, why does it work in the main page and some children? If it is wrapped, why aren't some components seeing that?

can't extend react extended class

I have more than 20 components in my react project. So doing the same thing for every component would be so unwise, so from oop concepts if I create a class with all the functionalities, then I can use it for all the objects I want.
In my case, I want to check if a user is logged in or not. If not redirect to '/login'. Now I have 'NavigationBar' inside each component, where I'm writing some code to redirect or not. But for a few seconds I can see then snap of each components, especially those large ones.
This is not also wise step
So here is what I tried next, created a component named Core extending React.Component, then I extended all component from it, but it gives me error directly.
What is the actual problem here? How this can be solved?
codesandbox.io
just add this line to Child.js
import React from "react";
React doesn't allow creation of component by subclassing defined component, the only way to create component is to extends directly the React.Component class, But react allow you to add extra behavior to defined component by using Higher-Order Components which has purpose to alter defined component by adding wrapper to and existing component
function wrapper(WrappedComponent) {
return class extends React.Component {
render() {
// Here you can add any logic you want
return (<div>
// Here you can add extra code
<h1>Code rendered by wapper</h1>
<WrappedComponent {...this.props} />;
</div>
}
}
}
And you use it like this
import wrapper from './wrapper';
import Child from './Child';
const HigherWrapper = wrapper(Child);
const rootElement = document.getElementById("root");
ReactDOM.render(<HigherWrapper />, rootElement);

component syntax in React

I'm a beginner in React, just some questions about component
Let's say I have a component :
function HelloWorld() {
return React.createElement('div', {}, 'Hello World!')
}
so my questions are:
1- HelloWorld is the component name, isn't it?
2- then I have the code below:
ReactDOM.render(
<HelloWorld/>, document.querySelector('#root')
);
what's the syntax of <ComponentName/>? isn't that more sensible to have the render function to be like:
ReactDOM.render(
HelloWorld(), document.querySelector('#root')
);
syntax of ReactDOM.render this :
ReactDOM.render( <Component />, id of DOM element where component will render );
in React there are 2 types of components :
1) functional components (also called stateless components)
2) class components (also called as stateful components
example of functional component :
function HelloWorld() {
return React.createElement('div', {}, 'Hello World!')
}
or
const HelloWorld=()=>{
return (<div>HelloWorld</div>);
}
export default HelloWorld;
example of class component :
class HelloWorld extends React.Component{
render(){
return (<div>HelloWorld</div>);
}
}
so passing component like this :
ReactDOM.render(
HelloWorld(), document.querySelector('#root')
);
is not correct way , in React you use Component as <ComponentName />
so thats why you have to pass like this :
ReactDOM.render(
<HelloWorld/>, document.querySelector('#root')
);
1 - No, that would be the contents (aka "children") of the div tag you are creating. That is <div>Hello World!</div>.
2 - Not sure what the ComponentName you are referring to is. The snippet takes the HelloWorld React component and mounts it to the DOM, which also starts the Reconciliation process.
Also, the purpose of JSX is to have a syntactic sugar that resembles HTML as much as possible. Yes, what you are suggesting is basically what happens behind the scenes (from a pseudo-code point of view), but would defeat the purpose of using JSX.
When react builds your app and run, it will be something like the last example that you gave.
React compile all components to
React.createElement('htmlTag' || someOtherComponent(), ...);
So a lot of people find more easy and productive to write your components using the JSX sintax and just use the build command to compile and bundle the code.

Invalid usage of this.props in react component

I'm getting the following error on webpack build and I don't understand why:
SyntaxError: this is a reserved word (11:5)
It occurs inside the Applicatons class at the code which says this.props.apps.map. Its trying to iterate through the passed apps property and create a JSX representation of Application components. I've included the Applications class as the first piece of code and the subsequent code shows how I instantiate the Applications component in a different class. I'm trying to access the props field inside the Applications class which extends the React Component
Here is the Applications class which I am clearly not using React props correctly:
import React from 'react';
import ReactDOM from 'react-dom';
import Application from './Application/Application';
import ErrorBoundary from '../ErrorBoundary/ErrorBoundary';
class Applications extends React.Component {
render(){
let applicationsList=null;
applicationsList = (
{this.props.apps.map((app,index)=>{
return <Application
name={app.name}
desc={app.desc}
changed={(event)=>this.props.changed(event,app.id)}
click={()=>this.props.clicked(index)}
key={app.id}
/>
})}
);
return (
{applicationsList}
)
}
}
And here is the code inside a different react component that instantiates the Applications component.
render(){
let applications=null;
applications = (
<div>
<Applications
apps={this.state.apps}
clicked={this.deleteApplicationHandler}
changed={this.nameChangedHandler}/>
</div>
);
return (<div>{applications}</div>);
}
I'm extremely new to react so i apologize if i missed anything if i did please let me know and ill update the question.
You're trying to use JSX templating syntax outside JSX. Curly brackets are interpreted as defining an object literal. Remove the extra brackets.
render(){
let applicationsList=null;
applicationsList = this.props.apps.map((app,index)=>{
return <Application
name={app.name}
desc={app.desc}
changed={(event)=>this.props.changed(event,app.id)}
click={()=>this.props.clicked(index)}
key={app.id}
/>
});
return applicationsList;
}

Resources