Benefits of composition over inheritance in React
I'm having a hard time substituting inheritance for composition in React. I'll try to explain the problem posed and my current solution, based on inheritance which is discouraged in the React style guide.
First, I define common state and methods in a super component:
export default class SuperComponent extends Component {
constructor(props) {
super(props);
this.state = commonState;
}
foo() {
this.setState({a: 3});
}
render() {
return (
<div>
{this.getContent()}
</div>
)
}
}
Then I make subcomponents with potentially more state and methods. These should also have access to the state of the supercomponent though:
export default class SubComponent1 extends SuperComponent {
constructor(props) {
super(props);
this.state = Object.assign(this.state, subComponent1State);
}
bar() {
this.setState({b: 7});
}
getContent() {
return (
<div>
I'm subcomponent 1
</div>
)
}
}
export default class SubComponent2 extends SuperComponent {
constructor(props) {
super(props);
this.state = Object.assign(this.state, subComponent2State);
}
bar() {
this.setState({c: 1});
}
getContent() {
return (
<div>
I'm subcomponent 2
</div>
)
}
}
When I try to convert this into an composition based approach I get this:
export default class SuperComponent extends Component {
foo() {
this.props.setStateMethod({a: 3});
}
render() {
return (
<div>
<div>
{this.props.text}
</div>
</div>
)
}
}
export default class SubComponent1 extends Component {
constructor(props) {
super(props);
this.state = Object.assign(commonState, subComponent1State);
}
bar() {
this.setState({b: 7});
}
render() {
return (
<SuperComponent
text={"I'm subcomponent 1"}
setStateMethod={this.setState}
subComponentState={this.state}
/>
)
}
}
export default class SubComponent2 extends Component {
constructor(props) {
super(props);
this.state = Object.assign(commonState, subComponent2State);
}
bar() {
this.setState({c: 1});
}
render() {
return (
<SuperComponent
text={"I'm subcomponent 2"}
setStateMethod={this.setState}
subComponentState={this.state}
/>
)
}
}
Is this a good way to go about converting the inheritance based solution to a composition based one? Isn't the inheritance based one better since common and differentiated state are better separated? In the composition based solution, one has to define common state in every sub component on initialisation.
reactjs inheritance composition
add a comment |
I'm having a hard time substituting inheritance for composition in React. I'll try to explain the problem posed and my current solution, based on inheritance which is discouraged in the React style guide.
First, I define common state and methods in a super component:
export default class SuperComponent extends Component {
constructor(props) {
super(props);
this.state = commonState;
}
foo() {
this.setState({a: 3});
}
render() {
return (
<div>
{this.getContent()}
</div>
)
}
}
Then I make subcomponents with potentially more state and methods. These should also have access to the state of the supercomponent though:
export default class SubComponent1 extends SuperComponent {
constructor(props) {
super(props);
this.state = Object.assign(this.state, subComponent1State);
}
bar() {
this.setState({b: 7});
}
getContent() {
return (
<div>
I'm subcomponent 1
</div>
)
}
}
export default class SubComponent2 extends SuperComponent {
constructor(props) {
super(props);
this.state = Object.assign(this.state, subComponent2State);
}
bar() {
this.setState({c: 1});
}
getContent() {
return (
<div>
I'm subcomponent 2
</div>
)
}
}
When I try to convert this into an composition based approach I get this:
export default class SuperComponent extends Component {
foo() {
this.props.setStateMethod({a: 3});
}
render() {
return (
<div>
<div>
{this.props.text}
</div>
</div>
)
}
}
export default class SubComponent1 extends Component {
constructor(props) {
super(props);
this.state = Object.assign(commonState, subComponent1State);
}
bar() {
this.setState({b: 7});
}
render() {
return (
<SuperComponent
text={"I'm subcomponent 1"}
setStateMethod={this.setState}
subComponentState={this.state}
/>
)
}
}
export default class SubComponent2 extends Component {
constructor(props) {
super(props);
this.state = Object.assign(commonState, subComponent2State);
}
bar() {
this.setState({c: 1});
}
render() {
return (
<SuperComponent
text={"I'm subcomponent 2"}
setStateMethod={this.setState}
subComponentState={this.state}
/>
)
}
}
Is this a good way to go about converting the inheritance based solution to a composition based one? Isn't the inheritance based one better since common and differentiated state are better separated? In the composition based solution, one has to define common state in every sub component on initialisation.
reactjs inheritance composition
Common state can be handled by container components hat inject the state as props. This is real separation of state because it is now owned by a dedicated component and others do not need to know how to manage that state. In your example the state of the sub components should be lifted up to the parent if they share that state.
– trixn
Jul 31 '18 at 0:14
add a comment |
I'm having a hard time substituting inheritance for composition in React. I'll try to explain the problem posed and my current solution, based on inheritance which is discouraged in the React style guide.
First, I define common state and methods in a super component:
export default class SuperComponent extends Component {
constructor(props) {
super(props);
this.state = commonState;
}
foo() {
this.setState({a: 3});
}
render() {
return (
<div>
{this.getContent()}
</div>
)
}
}
Then I make subcomponents with potentially more state and methods. These should also have access to the state of the supercomponent though:
export default class SubComponent1 extends SuperComponent {
constructor(props) {
super(props);
this.state = Object.assign(this.state, subComponent1State);
}
bar() {
this.setState({b: 7});
}
getContent() {
return (
<div>
I'm subcomponent 1
</div>
)
}
}
export default class SubComponent2 extends SuperComponent {
constructor(props) {
super(props);
this.state = Object.assign(this.state, subComponent2State);
}
bar() {
this.setState({c: 1});
}
getContent() {
return (
<div>
I'm subcomponent 2
</div>
)
}
}
When I try to convert this into an composition based approach I get this:
export default class SuperComponent extends Component {
foo() {
this.props.setStateMethod({a: 3});
}
render() {
return (
<div>
<div>
{this.props.text}
</div>
</div>
)
}
}
export default class SubComponent1 extends Component {
constructor(props) {
super(props);
this.state = Object.assign(commonState, subComponent1State);
}
bar() {
this.setState({b: 7});
}
render() {
return (
<SuperComponent
text={"I'm subcomponent 1"}
setStateMethod={this.setState}
subComponentState={this.state}
/>
)
}
}
export default class SubComponent2 extends Component {
constructor(props) {
super(props);
this.state = Object.assign(commonState, subComponent2State);
}
bar() {
this.setState({c: 1});
}
render() {
return (
<SuperComponent
text={"I'm subcomponent 2"}
setStateMethod={this.setState}
subComponentState={this.state}
/>
)
}
}
Is this a good way to go about converting the inheritance based solution to a composition based one? Isn't the inheritance based one better since common and differentiated state are better separated? In the composition based solution, one has to define common state in every sub component on initialisation.
reactjs inheritance composition
I'm having a hard time substituting inheritance for composition in React. I'll try to explain the problem posed and my current solution, based on inheritance which is discouraged in the React style guide.
First, I define common state and methods in a super component:
export default class SuperComponent extends Component {
constructor(props) {
super(props);
this.state = commonState;
}
foo() {
this.setState({a: 3});
}
render() {
return (
<div>
{this.getContent()}
</div>
)
}
}
Then I make subcomponents with potentially more state and methods. These should also have access to the state of the supercomponent though:
export default class SubComponent1 extends SuperComponent {
constructor(props) {
super(props);
this.state = Object.assign(this.state, subComponent1State);
}
bar() {
this.setState({b: 7});
}
getContent() {
return (
<div>
I'm subcomponent 1
</div>
)
}
}
export default class SubComponent2 extends SuperComponent {
constructor(props) {
super(props);
this.state = Object.assign(this.state, subComponent2State);
}
bar() {
this.setState({c: 1});
}
getContent() {
return (
<div>
I'm subcomponent 2
</div>
)
}
}
When I try to convert this into an composition based approach I get this:
export default class SuperComponent extends Component {
foo() {
this.props.setStateMethod({a: 3});
}
render() {
return (
<div>
<div>
{this.props.text}
</div>
</div>
)
}
}
export default class SubComponent1 extends Component {
constructor(props) {
super(props);
this.state = Object.assign(commonState, subComponent1State);
}
bar() {
this.setState({b: 7});
}
render() {
return (
<SuperComponent
text={"I'm subcomponent 1"}
setStateMethod={this.setState}
subComponentState={this.state}
/>
)
}
}
export default class SubComponent2 extends Component {
constructor(props) {
super(props);
this.state = Object.assign(commonState, subComponent2State);
}
bar() {
this.setState({c: 1});
}
render() {
return (
<SuperComponent
text={"I'm subcomponent 2"}
setStateMethod={this.setState}
subComponentState={this.state}
/>
)
}
}
Is this a good way to go about converting the inheritance based solution to a composition based one? Isn't the inheritance based one better since common and differentiated state are better separated? In the composition based solution, one has to define common state in every sub component on initialisation.
reactjs inheritance composition
reactjs inheritance composition
asked Jul 31 '18 at 0:02
HansHans
5217
5217
Common state can be handled by container components hat inject the state as props. This is real separation of state because it is now owned by a dedicated component and others do not need to know how to manage that state. In your example the state of the sub components should be lifted up to the parent if they share that state.
– trixn
Jul 31 '18 at 0:14
add a comment |
Common state can be handled by container components hat inject the state as props. This is real separation of state because it is now owned by a dedicated component and others do not need to know how to manage that state. In your example the state of the sub components should be lifted up to the parent if they share that state.
– trixn
Jul 31 '18 at 0:14
Common state can be handled by container components hat inject the state as props. This is real separation of state because it is now owned by a dedicated component and others do not need to know how to manage that state. In your example the state of the sub components should be lifted up to the parent if they share that state.
– trixn
Jul 31 '18 at 0:14
Common state can be handled by container components hat inject the state as props. This is real separation of state because it is now owned by a dedicated component and others do not need to know how to manage that state. In your example the state of the sub components should be lifted up to the parent if they share that state.
– trixn
Jul 31 '18 at 0:14
add a comment |
2 Answers
2
active
oldest
votes
First off, you should read React's Team response on the matter.
The code is pretty vague, so I can't tell if your case is really special, but I doubt it, so let me tackle the general consensus:
Inheritance and Composition are, in a vacuum, equally useful. In some languages or projects, you'll prefer a common class to inherit from, than a dozen functions to import and call, but in React, mainly because it's component-centric approach, the oposite is true.
Composition keeps React about just two things: props
and state
. You trust what you receive, act in a predictable way and reflect both props
and state
in what you render. If you need to change slightly what you render, you can send down different props
, maybe even make a component that wraps the first one for that specific use. That component can even have some logic on it's own, and pass it down through render props so you can control the result with even more precision. If you need to wrap different components with this logic you can make a HOC and wrap any component easily. At that point you can make dozens of components that return different things to the same props
and can switch between a library of components to display the data and to handle it.
Although things like Render props or HOCs look like different things, they are just techniques that use the already existing component logic and apply it in ways that let you reuse code and still make sense within React. Is it a good solution? Well, it works, but you end up in wrapping hell and juggling twenty concepts that are pretty much the same. That's why there is now a proposal for a paradigm changing new feature that is midway between inheritance and composition. But composition still makes less sense in the React way of doing things.
At the end of the day is just a different way of looking at the same problem. Composition just works better with React, and gives you more control in render
to mix and match what you need.
Again, if you have a practical example I could give you a better explanation applying different React techniques, but with your current one, clearly there isn't a good or bad way to do it, since it does nothing. This takes some time tinkering more than an explanation.
add a comment |
I don't think your solution is the best composition-based solution in this case. Since you want the subcomponents to have their own state (and I assume they will have their own logic), I would use a hoc like this:
// hoc.js
const withSuper = (SubComponent) => {
class WithSuper extends React.Component {
constructor(props) {
super(props);
this.foo = this.foo.bind(this);
}
foo() { // could also receive a value
this.props.setState({ a: 3 });
}
render() {
// Passes to the SubComponent:
// the state.a as a prop
// function foo to modify state.a
// the rest of the props that may be passed from above
return (
<SubComponent
a={this.state.a}
foo={this.foo}
{...this.props}
/>
)
}
}
return WithSuper;
};
// SubComponent1.js
class SubComponent1 extends Component {
constructor(props) {
super(props);
this.state = { b: 0 }; // or anything else
}
bar() {
this.setState({b: 7});
}
render() {
// to access the 'a' value use: this.props.a
// to modify the 'a' value call: this.props.foo()
return (
<div>
I'm subcomponent 1
</div>
);
}
}
export default withSuper(SubComponent1);
The SubComponent2
would also be wrapped: withSuper(SubComponent2)
, so it could also access a
and foo()
props.
I think this solution is better, because the hoc "Super" encapsulates the behavior of a
, and the sub-components only have to worry about modifying their specific state.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51603767%2fbenefits-of-composition-over-inheritance-in-react%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
First off, you should read React's Team response on the matter.
The code is pretty vague, so I can't tell if your case is really special, but I doubt it, so let me tackle the general consensus:
Inheritance and Composition are, in a vacuum, equally useful. In some languages or projects, you'll prefer a common class to inherit from, than a dozen functions to import and call, but in React, mainly because it's component-centric approach, the oposite is true.
Composition keeps React about just two things: props
and state
. You trust what you receive, act in a predictable way and reflect both props
and state
in what you render. If you need to change slightly what you render, you can send down different props
, maybe even make a component that wraps the first one for that specific use. That component can even have some logic on it's own, and pass it down through render props so you can control the result with even more precision. If you need to wrap different components with this logic you can make a HOC and wrap any component easily. At that point you can make dozens of components that return different things to the same props
and can switch between a library of components to display the data and to handle it.
Although things like Render props or HOCs look like different things, they are just techniques that use the already existing component logic and apply it in ways that let you reuse code and still make sense within React. Is it a good solution? Well, it works, but you end up in wrapping hell and juggling twenty concepts that are pretty much the same. That's why there is now a proposal for a paradigm changing new feature that is midway between inheritance and composition. But composition still makes less sense in the React way of doing things.
At the end of the day is just a different way of looking at the same problem. Composition just works better with React, and gives you more control in render
to mix and match what you need.
Again, if you have a practical example I could give you a better explanation applying different React techniques, but with your current one, clearly there isn't a good or bad way to do it, since it does nothing. This takes some time tinkering more than an explanation.
add a comment |
First off, you should read React's Team response on the matter.
The code is pretty vague, so I can't tell if your case is really special, but I doubt it, so let me tackle the general consensus:
Inheritance and Composition are, in a vacuum, equally useful. In some languages or projects, you'll prefer a common class to inherit from, than a dozen functions to import and call, but in React, mainly because it's component-centric approach, the oposite is true.
Composition keeps React about just two things: props
and state
. You trust what you receive, act in a predictable way and reflect both props
and state
in what you render. If you need to change slightly what you render, you can send down different props
, maybe even make a component that wraps the first one for that specific use. That component can even have some logic on it's own, and pass it down through render props so you can control the result with even more precision. If you need to wrap different components with this logic you can make a HOC and wrap any component easily. At that point you can make dozens of components that return different things to the same props
and can switch between a library of components to display the data and to handle it.
Although things like Render props or HOCs look like different things, they are just techniques that use the already existing component logic and apply it in ways that let you reuse code and still make sense within React. Is it a good solution? Well, it works, but you end up in wrapping hell and juggling twenty concepts that are pretty much the same. That's why there is now a proposal for a paradigm changing new feature that is midway between inheritance and composition. But composition still makes less sense in the React way of doing things.
At the end of the day is just a different way of looking at the same problem. Composition just works better with React, and gives you more control in render
to mix and match what you need.
Again, if you have a practical example I could give you a better explanation applying different React techniques, but with your current one, clearly there isn't a good or bad way to do it, since it does nothing. This takes some time tinkering more than an explanation.
add a comment |
First off, you should read React's Team response on the matter.
The code is pretty vague, so I can't tell if your case is really special, but I doubt it, so let me tackle the general consensus:
Inheritance and Composition are, in a vacuum, equally useful. In some languages or projects, you'll prefer a common class to inherit from, than a dozen functions to import and call, but in React, mainly because it's component-centric approach, the oposite is true.
Composition keeps React about just two things: props
and state
. You trust what you receive, act in a predictable way and reflect both props
and state
in what you render. If you need to change slightly what you render, you can send down different props
, maybe even make a component that wraps the first one for that specific use. That component can even have some logic on it's own, and pass it down through render props so you can control the result with even more precision. If you need to wrap different components with this logic you can make a HOC and wrap any component easily. At that point you can make dozens of components that return different things to the same props
and can switch between a library of components to display the data and to handle it.
Although things like Render props or HOCs look like different things, they are just techniques that use the already existing component logic and apply it in ways that let you reuse code and still make sense within React. Is it a good solution? Well, it works, but you end up in wrapping hell and juggling twenty concepts that are pretty much the same. That's why there is now a proposal for a paradigm changing new feature that is midway between inheritance and composition. But composition still makes less sense in the React way of doing things.
At the end of the day is just a different way of looking at the same problem. Composition just works better with React, and gives you more control in render
to mix and match what you need.
Again, if you have a practical example I could give you a better explanation applying different React techniques, but with your current one, clearly there isn't a good or bad way to do it, since it does nothing. This takes some time tinkering more than an explanation.
First off, you should read React's Team response on the matter.
The code is pretty vague, so I can't tell if your case is really special, but I doubt it, so let me tackle the general consensus:
Inheritance and Composition are, in a vacuum, equally useful. In some languages or projects, you'll prefer a common class to inherit from, than a dozen functions to import and call, but in React, mainly because it's component-centric approach, the oposite is true.
Composition keeps React about just two things: props
and state
. You trust what you receive, act in a predictable way and reflect both props
and state
in what you render. If you need to change slightly what you render, you can send down different props
, maybe even make a component that wraps the first one for that specific use. That component can even have some logic on it's own, and pass it down through render props so you can control the result with even more precision. If you need to wrap different components with this logic you can make a HOC and wrap any component easily. At that point you can make dozens of components that return different things to the same props
and can switch between a library of components to display the data and to handle it.
Although things like Render props or HOCs look like different things, they are just techniques that use the already existing component logic and apply it in ways that let you reuse code and still make sense within React. Is it a good solution? Well, it works, but you end up in wrapping hell and juggling twenty concepts that are pretty much the same. That's why there is now a proposal for a paradigm changing new feature that is midway between inheritance and composition. But composition still makes less sense in the React way of doing things.
At the end of the day is just a different way of looking at the same problem. Composition just works better with React, and gives you more control in render
to mix and match what you need.
Again, if you have a practical example I could give you a better explanation applying different React techniques, but with your current one, clearly there isn't a good or bad way to do it, since it does nothing. This takes some time tinkering more than an explanation.
edited Nov 28 '18 at 15:27
answered Nov 28 '18 at 15:20
Diego NosiDiego Nosi
565
565
add a comment |
add a comment |
I don't think your solution is the best composition-based solution in this case. Since you want the subcomponents to have their own state (and I assume they will have their own logic), I would use a hoc like this:
// hoc.js
const withSuper = (SubComponent) => {
class WithSuper extends React.Component {
constructor(props) {
super(props);
this.foo = this.foo.bind(this);
}
foo() { // could also receive a value
this.props.setState({ a: 3 });
}
render() {
// Passes to the SubComponent:
// the state.a as a prop
// function foo to modify state.a
// the rest of the props that may be passed from above
return (
<SubComponent
a={this.state.a}
foo={this.foo}
{...this.props}
/>
)
}
}
return WithSuper;
};
// SubComponent1.js
class SubComponent1 extends Component {
constructor(props) {
super(props);
this.state = { b: 0 }; // or anything else
}
bar() {
this.setState({b: 7});
}
render() {
// to access the 'a' value use: this.props.a
// to modify the 'a' value call: this.props.foo()
return (
<div>
I'm subcomponent 1
</div>
);
}
}
export default withSuper(SubComponent1);
The SubComponent2
would also be wrapped: withSuper(SubComponent2)
, so it could also access a
and foo()
props.
I think this solution is better, because the hoc "Super" encapsulates the behavior of a
, and the sub-components only have to worry about modifying their specific state.
add a comment |
I don't think your solution is the best composition-based solution in this case. Since you want the subcomponents to have their own state (and I assume they will have their own logic), I would use a hoc like this:
// hoc.js
const withSuper = (SubComponent) => {
class WithSuper extends React.Component {
constructor(props) {
super(props);
this.foo = this.foo.bind(this);
}
foo() { // could also receive a value
this.props.setState({ a: 3 });
}
render() {
// Passes to the SubComponent:
// the state.a as a prop
// function foo to modify state.a
// the rest of the props that may be passed from above
return (
<SubComponent
a={this.state.a}
foo={this.foo}
{...this.props}
/>
)
}
}
return WithSuper;
};
// SubComponent1.js
class SubComponent1 extends Component {
constructor(props) {
super(props);
this.state = { b: 0 }; // or anything else
}
bar() {
this.setState({b: 7});
}
render() {
// to access the 'a' value use: this.props.a
// to modify the 'a' value call: this.props.foo()
return (
<div>
I'm subcomponent 1
</div>
);
}
}
export default withSuper(SubComponent1);
The SubComponent2
would also be wrapped: withSuper(SubComponent2)
, so it could also access a
and foo()
props.
I think this solution is better, because the hoc "Super" encapsulates the behavior of a
, and the sub-components only have to worry about modifying their specific state.
add a comment |
I don't think your solution is the best composition-based solution in this case. Since you want the subcomponents to have their own state (and I assume they will have their own logic), I would use a hoc like this:
// hoc.js
const withSuper = (SubComponent) => {
class WithSuper extends React.Component {
constructor(props) {
super(props);
this.foo = this.foo.bind(this);
}
foo() { // could also receive a value
this.props.setState({ a: 3 });
}
render() {
// Passes to the SubComponent:
// the state.a as a prop
// function foo to modify state.a
// the rest of the props that may be passed from above
return (
<SubComponent
a={this.state.a}
foo={this.foo}
{...this.props}
/>
)
}
}
return WithSuper;
};
// SubComponent1.js
class SubComponent1 extends Component {
constructor(props) {
super(props);
this.state = { b: 0 }; // or anything else
}
bar() {
this.setState({b: 7});
}
render() {
// to access the 'a' value use: this.props.a
// to modify the 'a' value call: this.props.foo()
return (
<div>
I'm subcomponent 1
</div>
);
}
}
export default withSuper(SubComponent1);
The SubComponent2
would also be wrapped: withSuper(SubComponent2)
, so it could also access a
and foo()
props.
I think this solution is better, because the hoc "Super" encapsulates the behavior of a
, and the sub-components only have to worry about modifying their specific state.
I don't think your solution is the best composition-based solution in this case. Since you want the subcomponents to have their own state (and I assume they will have their own logic), I would use a hoc like this:
// hoc.js
const withSuper = (SubComponent) => {
class WithSuper extends React.Component {
constructor(props) {
super(props);
this.foo = this.foo.bind(this);
}
foo() { // could also receive a value
this.props.setState({ a: 3 });
}
render() {
// Passes to the SubComponent:
// the state.a as a prop
// function foo to modify state.a
// the rest of the props that may be passed from above
return (
<SubComponent
a={this.state.a}
foo={this.foo}
{...this.props}
/>
)
}
}
return WithSuper;
};
// SubComponent1.js
class SubComponent1 extends Component {
constructor(props) {
super(props);
this.state = { b: 0 }; // or anything else
}
bar() {
this.setState({b: 7});
}
render() {
// to access the 'a' value use: this.props.a
// to modify the 'a' value call: this.props.foo()
return (
<div>
I'm subcomponent 1
</div>
);
}
}
export default withSuper(SubComponent1);
The SubComponent2
would also be wrapped: withSuper(SubComponent2)
, so it could also access a
and foo()
props.
I think this solution is better, because the hoc "Super" encapsulates the behavior of a
, and the sub-components only have to worry about modifying their specific state.
// hoc.js
const withSuper = (SubComponent) => {
class WithSuper extends React.Component {
constructor(props) {
super(props);
this.foo = this.foo.bind(this);
}
foo() { // could also receive a value
this.props.setState({ a: 3 });
}
render() {
// Passes to the SubComponent:
// the state.a as a prop
// function foo to modify state.a
// the rest of the props that may be passed from above
return (
<SubComponent
a={this.state.a}
foo={this.foo}
{...this.props}
/>
)
}
}
return WithSuper;
};
// SubComponent1.js
class SubComponent1 extends Component {
constructor(props) {
super(props);
this.state = { b: 0 }; // or anything else
}
bar() {
this.setState({b: 7});
}
render() {
// to access the 'a' value use: this.props.a
// to modify the 'a' value call: this.props.foo()
return (
<div>
I'm subcomponent 1
</div>
);
}
}
export default withSuper(SubComponent1);
// hoc.js
const withSuper = (SubComponent) => {
class WithSuper extends React.Component {
constructor(props) {
super(props);
this.foo = this.foo.bind(this);
}
foo() { // could also receive a value
this.props.setState({ a: 3 });
}
render() {
// Passes to the SubComponent:
// the state.a as a prop
// function foo to modify state.a
// the rest of the props that may be passed from above
return (
<SubComponent
a={this.state.a}
foo={this.foo}
{...this.props}
/>
)
}
}
return WithSuper;
};
// SubComponent1.js
class SubComponent1 extends Component {
constructor(props) {
super(props);
this.state = { b: 0 }; // or anything else
}
bar() {
this.setState({b: 7});
}
render() {
// to access the 'a' value use: this.props.a
// to modify the 'a' value call: this.props.foo()
return (
<div>
I'm subcomponent 1
</div>
);
}
}
export default withSuper(SubComponent1);
edited Nov 28 '18 at 14:31
answered Nov 27 '18 at 18:27
pdpinopdpino
416
416
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51603767%2fbenefits-of-composition-over-inheritance-in-react%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Common state can be handled by container components hat inject the state as props. This is real separation of state because it is now owned by a dedicated component and others do not need to know how to manage that state. In your example the state of the sub components should be lifted up to the parent if they share that state.
– trixn
Jul 31 '18 at 0:14