Pass dynamic value to higher order component - reactjs

In my code I have to use the same lines of code at different places. So i thought that's the right time to put this code into a kind of base class. I've read about Higher-Order Components which seems to be the way to go and following some examples i ended up with the following code, which is not working. I've tried something around but was not able to get it work.
My HOC:
export interface HocProps {
DynamicId: string
}
const withDiv = (hocProps) => (BaseComponent) => {
return class extend React.Component {
render() {
return (
<div id={ hocProps.DynamicId }>
<BaseComponent />
</div>
);
}
}
}
export default withDiv;
A component to be wrapped by the div:
import withDiv from './MyHoc';
class MyComponent extends React.Component {
render() {
return (
<h3>Some content here</h3>
);
}
}
export default withDiv({ DynamicId: <dynamic value> })(MyComponent);
Another component, that uses MyComponent:
import MyComponent from './MyComponent';
export class OtherComponent extends React.Component {
render() {
return (
<div>
... Some content here ...
<MyComponent DynamicId={ 'id123' } />
</div>
);
}
}
I'd like to pass an id to in OtherComponent. Then in MyComponent this id has to be passed to the HOC as , which is not working. I only can pass static values to the HOC.
I'm new to react and I think i've made same mistake(s).
So my question is: What am i doing wrong and how is it done right?
Maybe there is another/better way for this?
Thanks in advance.
Edit:
I would expect this result:
<div>
... Some content here ...
<div id='id123'>
<h3>Some content here</h3>
</div>
</div>

There are two ways you can use HOCs according to your implementation.
I have created a sandbox, which will help you understand how to use HOCs.
One way is to extract your props out const hocWrapper = Component => props => { // return NewComponent and call it too }. Here you have to call your component while returning.
Other way is to destructure or use the props inside hocWrappers. const hocWrapper = Component => { // return NewComponent, you will receive props inside the newComponent and do what you wish}

Try this
const withDiv = (BaseComponent) => {
class CompWithDiv extends React.Component {
render() {
return (
<div id={this.props.DynamicId}>
<BaseComponent />
</div>
);
}
}
return CompWithDiv ;
}
export default withDiv;

Im not sure how you pass the dynamic values and whats wrong with it. but, you can just create your component like
export interface MyCustomProps {
customProp: string;
}
export interface MyCustomState {
something: string;
}
class MyComponent extends React.Component<MyCustomProps, MyCustomState>{
render(){<div>
... Some content here ...
<div>{this.props.customProp}</div>
</div>}
}
export default MyComponent
and use it in another component like
import MyComponent from './MyComponent';
export class OtherComponent extends React.Component {
render() {
return (
<div>
... Some content here ...
<MyComponent customProp={someDynamicStringValues}/>
</div>
);
}
}
and you can do it recursively

Related

How do I render a class (react component) passed as a prop?

import SomeComponent from 'Somewheere';
class MyPage {
render() {
return '<OtherComponent AcceptsSomeClass={SomeComponent} />';
}
}
in OtherComponent I want to be able to do
class OtherComponent {
render() {
return <this.props.AcceptsSomeClass open={true} someOtherProp={123}/>;
}
}
I want to be able to render SomeComponent inside OtherComponent. I know I can just pass a node or a function. But I've seen a library before that accepts a class like this and I want to pass the class so that I can control it more in OtherComponent instead of deciding how it renders in MyPage and passing it thee node/function.
In other words I want to pass a class (react component) as a prop and then be able to use it in the JSX.
What I did is that we are passing a function that renders a component, then we can call that function inside the OtherComponent to render it there.
class MyPage extends React.Component {
render() {
return <OtherComponent AcceptsSomeClass={() => <SomeComponent />} />
}
}
class OtherComponent extends React.Component {
render() {
return (
<div>
<p>Content inside OtherComponent</p>
{this.props.AcceptsSomeClass()}
</div>
)
}
}
class SomeComponent extends React.Component {
render() {
return <h1>HELLO WORLD!</h1>
}
}
ReactDOM.render(<MyPage />, document.getElementById('root'));
<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='root'></div>
An example of which you can pass components as props is when you are dealing with HOC (higher-order-components)
I use HOC to handle HTTP requests, for instance, using a modal to pop up on the screen with the loading / error when fetching /putting data, or authentication.
I will present you with a simple example:
import React from 'react'
import Modal from 'modal' //this would be a modal covering the screen
const httpHandler = WrappedComponent => {
const wrappedComponent = props => {
//handle some logic here, coded here, or as a result from some middleware
return (
<Fragment>
<Modal>...</Modal> //handle the HTTP async stuff here, like loading,
//or authentication, or an error message
<WrappedComponent {...props} />
</Fragment>
)
}}
You can call this inside a Component like this when you export another component
//all of the component stuff above
export default httpHandler(WrappedComponent)

how to add a function of a class into another function in a component?

How to add RenderFunction of class of SayHello into RenderView function?
For clarity, please look at the following picture and code.
this is my code:
import React from 'react';
class SayHello{
RenderFunction() {
return (
<p>Hello</p>
);
}
}
function RenderView(){
return (
<div>
//I want to add RenderFunction of class of SayHello into here.
</div>
);
}
const DishDetail = () => {
return(
<div>
<RenderView />
</div
);
}
export default DishDetail;
I believe the following is what you are looking for, if I am understanding the problem you are asking. The following can be seen working here: https://codesandbox.io/s/7ykk0z90yx
Firstly we are going to be extending our react component, we can do this in two way, we can destructure from the react import like the following.
import React, { Component } from 'react';
Or we can just directly write it:
class SayHello extends React.Component
Secondly we need to call our SayHello component like we would with any other component we want to use.
Also as we are using arrow functions, I went with this approach for the RenderView component.
And with the above we have the following:
class SayHello extends Component {
render() {
return <p>Hello</p>;
}
}
const RenderView = () => {
return (
<div>
<SayHello />
</div>
);
};
const DishDetail = () => {
return (
<div>
<RenderView />
</div>
);
};
Hope the above helps and answers your question. I have also tidied up your code. For example your original code is missing an ending > on it's div. Which obviously will not make it compile/help.
did you try like this?
class SayHello{
RenderFunction = () => {
return (
<p>Hello</P>
);
}
}
function RenderView(){
return SayHello.RenderFunction();
}
If RenderFunction doesn't depend on SayHello instance, it shouldn't be a part of this class.
It appears like stateless function component and can be used as such because this is how composition is commonly implemented in React:
function RenderFunction() {
return (
<p>Hello</P>
);
}
class SayHello{
// can use <RenderFunction> too if necessary
}
function RenderView(){
return <RenderFunction/>
}
In case RenderFunction depends on SayHello instance (this.state), this is a different problem because accessing RenderFunction isn't enough. On the contrary, RenderFunction shouldn't be additionally called because this will create additional Modal instances. It's existing SayHello component instance that needs to be accessed in other components.
SayHello should be a parent or a sibling to components that need to interact with a modal.
There should exist a reference to SayHello instance:
<SayHello ref={this.modalContainerRef}/>
Then a modal can be reached as this.modalContainerRef.current.toggleModal() in parent component. A callback that allows to call toggleModal can be passed to child components through props or context API.
extend your class from Component.
export class SayHello extends Component {...}
move your RenderFunction into render as arrow function.
put <SayHello /> into methodof RenderView.
View the correct code below:
import React, { Component } from 'react';
export class SayHello extends Component {
render(){
RenderFunction = ()=> {
return (
<p>Hello</p>
);
}
return(
{RenderFunction()}
);
}
}
function RenderView(){
return (
<div>
<SayHello />
</div>
);
}
const DishDetail = ()=>{
return(
<div>
<RenderView />
</div
);
}
export default DishDetail;

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 />

Try to call a component inside a component - React

So I started with React and I have these two Components.
In the first component I want to iterate an array of objects with the map() function (which works) and call the other component that for now just returns a simple h1 tag.
Well, nothing is been called and there is no error in the console.
I believe the problem is in the return sentence in the renderAvatarData()
(if I do console.log after the return sentence it seems to not get there but if the console.log is before the return it invokes)
HomePageBoxesData.js
import React, { Component } from 'react';
import AvatarDetails from './AvatarDetails';
class HomePageBoxesData extends Component{
constructor(props) {
super(props);
};
renderAvatarData(){
this.props.data.map(data => {
return <AvatarDetails data={data}/>
});
}
render(){
return(
<div>
{this.renderAvatarData()}
</div>
);
}
};
export default HomePageBoxesData;
AvatarDetails.js
import React, { Component } from 'react';
class AvatarDetails extends Component{
constructor(props) {
super(props);
};
render(){
return(
<h1>Hello World</h1>
);
}
};
export default AvatarDetails;
Issue is in renderAvatarData() method, you forgot to use return with map, Use this:
renderAvatarData(){
return this.props.data.map((data)=>{
return <AvatarDetails data={data}/>
});
}
Since you just want to return the Component, you can directly write it like this:
renderAvatarData(){
return this.props.data.map(data => <AvatarDetails data={data} /> );
}
i agree with Mayank Shukla but i usually use this method in this case:
render() {
return(
<div>
_.map(this.props.data, function(value, key){
return(
<AvatarDetails key={key} data={value} />
)
})
</div>
i am not sure if there is one better than the other

react dynamic render with number

my page.js
class R1 extends React.Component {
render() {
return (
<div className="r1">
<h1>level1</h1>
</div>
);
}
}
class R2 extends React.Component {
render() {
return (
<div className="r2">
<h1>level2</h1>
</div>
);
}
}
my main.js
important * as Page from './page';
class App extends React.Component {
render() {
return (
<div className="r1">
<Page.R+level/>
</div>
);
}
}
Skip getInitialState,
I want to dynamic render with level.
I try React.renderComponent(<Page.R+this.state.level />, document.body);
It's not working with failed: SyntaxError
Is there more easily way? or is dynamic render available?
thanks
Not sure how you are exporting your Components so there is an assumption here, generally it is convention to put them in different files.
You can render in your parent component using an if statement inside JSX like this:
class App extends React.Component {
render() {
var renderPage;
if (something) {
renderPage = <PageOne />;
} else {
renderPage = <PageTwo />;
}
return (
<div>
{renderPage}
</div>
);
}
}
main.js can be modified like this to achieve what you want
import * as Page from './page';
class App extends React.Component {
render() {
const level = 2;
return (
<div className="r1">
{/*You use loop over list to get value of level and render all the pages*/}
{React.createElement(Page[`R${level}`], null)}
</div>
);
}
}
Page is an object and we are trying to access the pages and rendering the component name which is in string type.

Resources