React: how-to override child component - reactjs

Which is the best way to override a child component?
check if this.props.children != null
passing the component with props
?
Example component
class ParentComponent extends Component {
render() {
<div>
<ChildComponent />
</div>
}
}
Solution 1
class ParentComponent extends Component {
render() {
<div>
{this.props.children ? this.props.children : <DefaultChildComponent/>}
</div>
}
}
<ParentComponent><MyChildComponent/></ParentComponent>
Solution 2
class ParentComponent extends Component {
render() {
<div>
{this.props.child}
</div>
}
}
Parent.defaultProps = { child: <DefaultChildComponent /> }
const myChildComponent = <MyChildComponent/>
<ParentComponent child={myChildComponent}/>
Solution 3?

What you are asking is slightly confusing as you are checking for this.props.children but then rendering other components rather than the children.
I would have thought the best way would be;
class ParentComponent extends Component {
render() {
<div>
{
this.props.children
? this.props.children
: <DefaultChildComponent />
}
</div>
}
}
Then use it as either;
<ParentComponent />
Which just renders your default child component
or
<ParentComponent><div>Can Be Any Child</div></ParentComponent>
Which you can pass any component is as this children which will then be rendered.

Related

How can I pass data from a component array to an another component with props?

I need a little help. I'm working on a project that uses Class Components in React and I got stuck with a issue.
How can I pass datas using props?
For example, imagine that I have one Component that have an array in the state:
import React,{Component} from "react";
class CarList extends Component{
constructor(props){
super(props);
this.state = {
carList: ['Jeep', 'Kwid','HB20','Ônix', 'Prisma', 'Gol quadrado']
}
}
render(){
return(
<div>
</div>
);
}
}
export default CarList;
And now I have to call this array in a Option Tag inside a Select Tag.
Let's imagine this component Bellow:
import React from "react";
import { Component } from "react";
import CarList from "./components/Datas";
class App extends Component{
render(){
return(
<div>
<p>I got it! Here is the car list:</p>
<select>
{this.state.CarList.map( (item,x)=>{
return(
<option key={x}>{item}</option>
)
})}
</select>
</div>
)
}
}
export default App;
This piece of code does not work.
the console.log says: "Uncaught TypeError: this.state is null"
I know that I could create a div with my datas and call with , but I have to use props to pass the datas between the Components.
How can I create a callback function using props to resolve this?
Hi!
I tried to call using this.state, but I got "this.state is not defined"
To pass your data as a props you have to pass it to your child component like this from your parent component :
class ParentComponent extends React.Component {
state = {
carList: [],
};
constructor(props) {
super(props);
this.state = {
carList: ['Jeep', 'Kwid', 'HB20', 'Ônix', 'Prisma', 'Gol quadrado'],
};
}
render() {;
return (
<div>
<ChildComponent carList={this.state.carList || []} />
</div>
);
}
}
and then it is accessible in your child component with this.props.
you can use this props in child component like this:
class ChildComponent extends React.Component {
render() {
return (
<div>
{this.props.carList.map((cars, index) => {
return (
<span key={index}>
{cars}
<br />
</span>
);
})}
</div>
);
}
}
Edit -
if you want to see source code : https://stackblitz.com/edit/react-ts-ddcylu?file=Parent.tsx

How to pass an Array between two sibilings in react

In my project I have App.js that is Parent component. And for Parent component there are two child components those are Childone component and Childtwo component. Now I am trying to pass data from Childone component to Childtwo component. Someone please tell me to achieve this
This is App.js
import React, { Component } from "react";
import Childone from "./Childone/Childone";
import Childtwo from "./Childtwo/Childtwo";
class App extends Component {
render() {
return (
<div className="App">
<Childone />
<Childtwo />
</div>
);
}
}
export default App;
This is Childone
import React, { Component } from "react";
class Childone extends Component {
render() {
const Employs = ["Mark", "Tom"];
return <div className="Childone" />;
}
}
export default Childone;
This is Childtwo
import React, { Component } from "react";
class Childtwo extends Component {
render() {
return <div className="Childtwo" />;
}
}
export default Childtwo;
If you feel I am not clear with my doubt, please put a comment.
There are two ways of doing it.
By passing data from Childone to Parent through callback and from Parent to Childtwo as prop. Thereby letting parent be the intermediatory.
By creating a context at the parent and let Childone be the producer and Childtwo be the consumer.
Context is used to avoid prop drilling. Also frequent update of context values isn't considered as a good practice.
Also, for your case we can go with approach ( 1 ).
You can enter data in Childone and see the data reflect in Childtwo in this sandbox.
Are you familiar with React's unidirectional data flow? I would try to create a mental model in your head of having the Parent be the container/controller that passes the required information into your children.
So in this case you would either want the data to originate from Parent or have some event handler associated with the data in Child1. If the latter, attach a callback function from Parent to Child1 that accepts the data as an argument to then be passed into Child2.
best solution is is to use redux. If you are not familiar with redux then you can follow below approach :
import React, { Component } from "react";
import { render } from "react-dom";
import "./style.css";
class App extends Component {
constructor() {
super();
this.state = {
number:[0]
};
}
render() {
return(
<div>
<div>Parent Componet</div>
<Child1 passToChild={this.passToChild.bind(this)}> </Child1>
<Child2 number={this.state.number}></Child2>
</div>
)
}
passToChild(number){
this.setState({
number : [...this.state.number,number]
});
}
}
class Child1 extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<div>Child1</div>
<button onClick={() => this.sendToSibiling()}>
Send data to sibiling
</button>
</div>
);
}
sendToSibiling() {
this.props.passToChild(Math.random());
}
}
class Child2 extends Component {
constructor(props) {
super(props);
}
render(){
return(
<div>
<div>Child 2</div>
<span>data from sibiling : {...this.props.number}</span>
</div>
)
}
}

In React, can I create a Component that also acts as a Forwarded Ref object?

I have a need to use forwarded refs
const InfoBox = React.forwardRef((props, ref) => (
<div ref={ref} >
<Rings >
</Rings>
<Tagline />
</div>
));
I also happen already have the code written like this
class InfoBox extends React.Component {
constructor(props) {
super(props)
}
render () {
return (
<div >
<Rings />
<Tagline />
</div>
)
}
basically my InfoBox needs to be a Component because it holds some state, but I also want it to behave like an object that can receive refs from the parent and forward them down to the children (basically React.forwardRef)
After familiarizing myself with React.forwardRef, I can't figure out how to get it to work with my existing React components, which already have functionality attached to state.
do I need to separate the two objects, and wrap one within the other or is there a way I can achieve this in the same object?
the code that wraps Infobox looks like
class AppContainer extends React.Component {
constructor(props) {
super()
this.infobox_ref = React.createRef()
}
componentDidMount() {
// this.infobox_ref.current.innerHTML should return the inner HTML of the infobox
}
render() {
return (
<InfoBox ref={this.infobox_ref}>
)
}
am I using forwarded refs correctly?
In React, the ref prop is not forwarded by default. In order to get a reference in a child component, you have 2 options:
Using a function component wrapped in the forwardRef function. You have already done this:
const InfoBox = React.forwardRef((props, ref) => (
<div ref={ref} >
<Rings >
</Rings>
<Tagline />
</div>
));
Changing the name of the ref prop.
// Parent Component
class AppContainer extends React.Component {
constructor(props) {
super()
this.infobox_ref = React.createRef()
}
componentDidMount() {
// this.infobox_ref.current.innerHTML should return the inner HTML of the infobox
}
render() {
return (
<InfoBox infoboxRef={this.infobox_ref}>
)
}
}
// Child Component
class InfoBox extends React.Component {
render () {
return (
<div ref={this.props.infoboxRef}>
<Rings />
<Tagline />
</div>
)
}
}
Of course, you can also combine them, allowing you to still pass to the ref prop from the parent, but consuming the "fixed" prop in the child class component, as shown here by #tubu13:
class InfoBox extend React.Component{
render() {
return (
<div ref={this.props.infoboxRef}>
<Rings />
<Tagline />
</div>
)
}
}
export default React.forwardRef((props, ref) => <InfoBox {...props} infoboxRef={ref} />)

Can I write Component inside Component in React?

I have come across many sources which talk about how to do Component nesting. However, whenever I try to create a Component inside another Component my code fails.
class parent extends React.Component{
class child extends React.Component{
render(){
return <div><h1>Hiiii</h1></div>;
}
}
render(){
return <div><DEF /></div>;
}
}
You can't do that. You can do this on the same file (not same component)
class DEF extends Component {
render() {
return (
<div>
<h1>Hiiii</h1>
</div>
);
}
}
export default class ABC extends Component {
render() {
return (
<div>
<DEF />
</div>
);
}
}
You can't define class inside another class and I don't see why you would want to.
In React you can define Components in two ways: a stateful component (class) or a functional component (function). Stateful components should only be used when you need to manage state locally.
You can do something like:
export default class MyStatefulComponent extends Component() {
render() {
return (
<div><MyFunctionalComponent {...this.props} /></div>
)
}
}
function MyFunctionalComponent(props) {
return <h1>I am functional</h1>
}
I have used the spread operator to pass on the props from the stateful to the functional component, but you should probably pass the individual props as needed..
Comoponent nesting means rendering react components inside other components. Like
<ParentComponent property={value}>
<div>
<ChildComponent />
...
</div>
</ParentComponent>
This is how you can achieve what you are trying to do.
class ABC extends React.Component {
render() {
class DEF extends React.Component {
render() {
return (
<div>
<h1>Hiiii</h1>
</div>
);
}
}
return (
<div>
<DEF />
</div>
);
}
}
Yo can just define component as a static property of other component
class Test extends Component {
static SubTest=props=><div>SubTet</div>
render(){
return(
<div>Test component</div>
)
}
<Test />
<test.SubTest />

React. How to pass props inside a component defined on a prop?

If we have the following structure on a React application:
class BasePage extends React.Component {
render() {
return <div>
{this.props.header}
{/*<Header title={this.props.title} />*/}
</div>
}
}
BasePage.defaultProps = {
header: <header>Base Page</header>
}
class Header extends React.Component {
render() {
return <header>
<h1>{this.props.title}</h1>
</header>
}
}
class TestPage extends BasePage {
}
TestPage.defaultProps = {
header: <Header />
}
class Root extends React.Component {
render() {
return <div>
<TestPage
title="Test Page Title"
/>
</div>
}
}
ReactDOM.render(
<Root />,
document.getElementById('root')
)
If we have a common component like <Header /> we can pass a title property easily like <Header title={this.props.title} />.
But how can we pass props inside a component if this component is defined as a prop itself?
For example, how can we do something like:
{this.props.header title={this.props.title}}
So it will render the Test Page Title correctly?
Important note: we could overwrite the render method inside the Test component. But the purpose of this question is to solve this problem without doing this.
Firstly, props are read-only and a component should never be update it's own props, so lines like
componentWillMount() {
this.props.header = <header>Base Page</header>
}
should not be used. defaultProps can do what I think you are trying to do:
class BasePage extends React.Component {
render() {
return <div>
{this.props.header}
{/*<Header title={this.props.title} />*/}
</div>
}
}
BasePage.defaultProps = {
header: <header>Base Page</header>
}
Secondly, inheritance is not often done in React. I'm not saying don't do what your'e doing, but take a read of the docs and see if there is perhaps a simpler way to achieve the same goals.
Finally, setting props on components passed as props. There are a couple different ways to do this.
If you pass the Component rather than the <Component /> you can add props like normal:
ChildComponent = (props) => {
const HeaderComponent = props.header
return <HeaderComponent title="..." />
}
ParentComponent = () => <ChildComponent header={Header} />
You can clone the element to override props:
ChildComponent = (props) => {
const HeaderComponent = React.cloneElement(props.header. { title: "..." })
return <HeaderComponent />
}
ParentComponent = () => <ChildComponent header={<Header />} />
NOTE: I have used functional components instead of class components for brevity, but the concepts are the same.
This seems like a great use case for React.cloneElement.
React.cloneElement(this.props.header, { title: this.props.title });
It returns a clone of the component with the new props included.

Resources