Can I call react component in a react component - reactjs

I'm just start learning react js. Just wondering is it a good way to invoke a component inside another component?

Most React projects will start out by giving you an App.js component where you can start writing code. There, you can invoke other components using JSX syntax. Like this:
function App() {
return (
<div>
<Header />
<Main />
<Footer />
</div>
)
}
Working example below:
// Main application component
function App() {
return (
<div>
<Header />
<Main />
<Footer />
</div>
)
}
// Header component
function Header() {
return (
<header>
<h1>My first React App</h1>
</header>
)
}
// Main component
function Main() {
return (
<main>
<p>Stuff and stuff go here..</p>
</main>
)
}
// Footer component
function Footer() {
return (
<footer>
<p>Copyright 2020</p>
</footer>
)
}
ReactDOM.render(
<App />,
document.getElementById('app')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Note: You may also see class components instead of functional ones. They look something like this:
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
// some state goes here..
}
}
render() {
return (
<div>
<Header />
<Main />
<Footer />
</div>
)
}
}

You generally want to compose components using JSX. There is a good write up on the react docs. https://reactjs.org/docs/composition-vs-inheritance.html
const ComponentOne = () => <div>hi</div>
const ComponentTwo = () => <div>two</div>
const ComponentThree = () => (
<>
<ComponentOne />
<ComponentTwo />
</>
)

In the case that you want to learn, or start to le I recommend this https://reactjs.org/docs/getting-started.html. If you have another question please let me know.

React has two type of components: Function based and Class based. I will explain Function based components.
Example:
import React, {Fragment} from 'react';
function ComponentB(){
return (
<p>Hello i'm component B</p>
)
};//end;
function ComponentA(){
return (
<Fragment>
<h1>hello i'm component A</h1>
<ComponentB />
</Fragment>
)
};//end;
export default ComponentA;

Related

React JSX to string

How can I convert the children of a React component to a string without it rendering?
import { renderToString } from 'react-dom/server';
const MyComponent = () => {
return (
<h1>Hello</h1>
)
}
const Output = () => {
return (
<pre>
{renderToString(
<div>
<MyComponent />
<MyComponent />
<MyComponent />
</div>
}
</pre>
)
}
How can I make the above show:
<div>
<MyComponent />
<MyComponent />
<MyComponent />
</div>
instead of
<div>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
</div>
Ultimately I'm looking to show how the code for the component is written in a ui system. Trying to parse the children instead of writing the component twice. Any examples of open source websites demonstration ui components with a code block works too, and I'll just look into that.
Take a look at react-code-blocks. Basically you can add any code, just like Stackoverflow.

Is it possible to hide a parent component from child component in React.js?

As shown in the Flowchart (Flowchart), I want to hide the Header component if Main component renders the Login component. But if the Main component renders the Home component, I want to display the Header component.
This is App.js file:
import React from 'react'
import Header from 'Header'
import Main from 'Main'
import Footer from 'Footer'
function App() {
return (
<div className="App">
<Header />
<Main />
<Footer />
</div>
)
}
export default App;
This is Main.js file:
import React from 'react'
import Home from './Home'
import Login from './Login'
function Main() {
let user = true //Toggled by users
return (
<div>
{
user ? ( <Home /> ) : ( <Login /> )
}
</div>
)
}
export default Main
Putting the Header Component in Home itself will not solve the problem as I have to add much more pages and adding a Header component in every page doesn't seem efficient.
That's a use case of lifting the state up, here your user state should be in the scope of Header and Main.
Then just pass the user (isLogged in the example) to Main, via props or Context API.
function Main({ isLogged, toggleLogin }) {
return (
<div>
<button onClick={toggleLogin}>toggle</button>
{isLogged ? <>Home</> : <>Login</>}
</div>
);
}
function App() {
const [isLogged, toggle] = useReducer((p) => !p, false);
return (
<div className="App">
{!isLogged && <>Header</>}
<Main isLogged={isLogged} toggleLogin={toggle} />
<>Footer</>
</div>
);
}

How can I wait for init config to complete?

I've this code
class ConnectedApp extends Component {
constructor(props) {
super();
props.initConfig(); // the ajax call that populate the user settings
}
render() {
return (
<I18nextProvider i18n={i18n}>
<Router>
<div className="App" style={appStyle}>
<Head/>
<div className="Container">
<Container/>
</div>
<Foot/>
<Loading/>
<ToastContainer position="bottom-right" />
</div>
</Router>
</I18nextProvider>
);
}
}
Now the problem is that the initconfig is an ajax function in middleware. Before rendering the app for logged user I need to wait that the function has finished. Anyone have some suggestion?
Actually the app works nut on first login give an error and that error is resolved by manual refresh.
You'll need to change a few things here– Firstly you will need some way to indicate loading. This can be done in it's simplest form using a boolean either in your global or local state. You should also move your AJAX call method into the appropriate component lifecycle method componentDidMount.
You want it in your componentDidMount to ensure the component is mounted and ready to receive props or state changes.
class ConnectedApp extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
this.props.initConfig();
}
render() {
if (this.props.loading === true) {
return null // this will render nothing until loading is `false`
}
return (
<I18nextProvider i18n={i18n}>
<Router>
<div className="App" style={appStyle}>
<Head/>
<div className="Container">
<Container/>
</div>
<Foot/>
<Loading/>
<ToastContainer position="bottom-right" />
</div>
</Router>
</I18nextProvider>
);
}
}
In your redux state you would want to set a property for the loading state. When you start the request, you would set loading to true, when it is successful set it to false. If it fails, you would need a more expandable solution to account for that other than a simple 'loading' boolean.
Also, if you haven't checked out the new React Hooks API, this is what your component would look like using that.
import React, { useEffect } from "react";
const ConnectedApp = ({ initConfig, loading }) => {
useEffect(() => {
initConfig() // this will only get called when the component mounts. Same as `componentDidMount`
}, [])
if (loading === true) {
return null // this will render nothing until loading is `false`
}
return (
<I18nextProvider i18n={i18n}>
<Router>
<div className="App" style={appStyle}>
<Head/>
<div className="Container">
<Container/>
</div>
<Foot/>
<Loading/>
<ToastContainer position="bottom-right" />
</div>
</Router>
</I18nextProvider>
);
}

Adding a Link as a child of a Router with ReactDOM.render yields "You should not use <Link> outside a <Router>"

I am looking for a way to use ReactDOM.render to create a Link within a react router. The setup more or less looks like this:
const router = (
<div>
<Router>
<Route path="/map" component={Map}/>
</Router>
</div>
);
The relevant parts of Map.jsx look like this:
const MapPopup = () => {
return (
<Link to={`/map/add`} />
)
}
class Map extends React.Component {
componentDidMount() {
this.map = L.map('map')
//...stuff...
this.map.on('contextmenu', event => {
popup
.setLatLng(event.latlng)
.addTo(this.map)
.setContent(
ReactDOM.render(
MapPopup(),
document.querySelector('.leaflet-popup-content')
)[0]
)
.openOn(this.map)
})
}
render() {
return (
<React.Fragment>
<div id="map" />
</React.Fragment>
)
}
}
I am basically trying to add a Link to the map popup provided by leaflet (I can't use react-leaflet for this project). If I however return the MapPopup directly in the render function it works (obviously not in the popup but the Link does work this way).
<React.Fragment>
<div id="map" />
<MapPopup />
</React.Fragment>
Does anyone have an idea how I can tackle this rather unusual problem?
I am using "react-router-dom": "4.3.1".
This is the expected error since <Link> component expects ancestor component to be of router type (<BrowserRouter>, <MemoryRouter>, <Router> ... ), refer this thread for a more details.
For your scenario to circumvent this limitation ReactDOM.createPortal could be utilized instead of ReactDOM.render:
<Route
path="/popup"
render={() => (
<Popup>
<div>
Some content goes here
<Link to="/map"> Back to map</Link>
</div>
</Popup>
)}
/>
where
class Popup extends React.Component {
render() {
return ReactDOM.createPortal(
this.props.children,
document.querySelector("#link-render-div")
);
}
}
and
Here is a demo for your reference

React adding an element programmatically with a HOC

Is there a way using a High Order Component to add elements programatically to a Component? I was wondering if there was a way using React.createElement to append the component's children? Here is the code that I have so far:
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
function addAnElement(WrappedComponent) {
return class Enhancer extends WrappedComponent {
render() {
const elementsTree = super.render()
// Programatically add a child?
// Update elementTree.props.children somehow?
return elementsTree
}
}
}
class JustSomeText extends Component {
render() {
return (
<div>
<p>A long time ago, in a galaxy far, far away.</p>
{/* I want to add an element here? */}
</div>
)
}
}
function App() {
const ExtendedComponent = addAnElement(JustSomeText)
return (
<div className="App">
<ExtendedComponent />
</div>
)
}
export default App
ReactDOM.render(<App />, document.getElementById('root'))
I'm also interested in other, more effective ways to achieving the same result.
The simplest way to achieve this (although it does not use HOC) is using the children prop in React.
class JustSomeText extends Component {
render() {
return (
<div>
<p>A long time ago, in a galaxy far, far away.</p>
{this.props.children}
</div>
)
}
}
function App() {
return (
<div className="App">
<JustSomeText>
<p>more text!</p>
</JustSomeText>
</div>
)
}
This will render the following:
<div className="App">
<div>
<p>A long time ago, in a galaxy far, far away.</p>
<p>more text!</p>
</div>
</div>
Refer to this for further detail on children - https://reactjs.org/docs/composition-vs-inheritance.html

Resources