For example I have a store:
class MyStore {
constructor() {
this.value = 1;
}
}
I need to get and change MyStore.value in a view.
I can do it:
class MyView extends React.Component {
constructor() {
super();
this.state = {
value: MyStore.getValue()
};
}
And change it:
userClick() {
this.setState({value: MyStore.changeValue('newValue')});
}
Or change value in a store and call emit.
But I can do it with forceUpdate():
render() {
const value = MyStore.value;
return (
<div>{value}</div>
)
}
And change it:
userClick() {
MyStore.value = 'newValue';
this.forceUpdate();
}
Why is it bad?
I don't think there is anything wrong in what you are trying to do. You are "just" following basic OO-rules and are encapsulating your data.
Actually I don't understand why most basic React examples don't introduce this pattern, instead of mixing data and presentation. Usually you don't see stuff like stores before you reach examples involving, Flux, Redux or MobX (which I think is the way for you to go).
I have rewritten your example in this codepen to use getters and setters and I'm using the observer pattern to notify when data has changed.
I would claim that this (remember it's a quick demo) is a perfectly OK way to use forceUpdate().
class MyView extends React.Component {
constructor(props) {
super(props);
this.props.store.setObserver(this);
}
changed(){
this.forceUpdate();
}
render() {
return (
<div>
<button onClick={()=>this.props.store.value = Math.random()}>Change</button>
<p>{this.props.store.value}</p>
</div>
)
}
}
class MyStore {
constructor() {
this._value = 1;
}
get value() {
return this._value;
}
set value(val) {
console.log(val);
this._value = val;
this._observer.changed();
}
setObserver(observer){
this._observer = observer;
}
}
Actually this is what the mobX library is doing under the surface. It provides you with automatic listener-capacities, and if this is the way you plan to go I definitely advice you to take a look at this library.
It will handle all the "observer" details, including forceUpdate() automatically (it does not use forceUpdate, but calls your render() method when an updata is required).
With mobX the example boilds down to (using a functional component, since it does not need state)
var View = observer((props) => (
<div>
<button onClick={()=>props.store.value = Math.random()}>Change</button>
<p>{props.store.value}</p>
</div>
)
)
class MyStore {
#observable value =1;
get value() { return this._value; }
set value(val) { this._value = val; }
}
Se live demo on codepen.io
Related
I just update to the react 16.3. I have a value to keep tracking of a value that I need to post to the server. I want to save this.value after some props changed. I found out that a lot of life cycle functions are deprecated. And I cannot save the value into redux before rendered. Could anyone give me a good way to handle it? Thanks.
class Foo extends Component {
constructor(props) {
super(props);
this.value = {};
}
render() {
return (
//some other components
<Bar onChange={value => this.value = value} />
)
}
}
I would most likely handle it with this
class Foo extends Component {
state = {
text: ''
}
render() {
return (
//some other components
<Bar onChange={value => this.setState({text:value})} />
)
}
}
Keep in mind this is ES7 way to do it. A bit cleaner than doing it in constructor(). If you don't use new syntax just initiate state in constructor as,
constructor(props){
super(props)
this.state = {
text: ''
}
}
if you would like to get your hands dirty more with handling value that user is giving could also pass onChange value to own function and setState on there. Many prefer it that way.
e.g.
handleChange = (text) => {
// Some amaizing text manipulation
this.setState({text})
}
render() {
return (
//some other components
<Bar onChange={this.handleChange} />
)
}
and with redux dispatch function
constructor(props) {
super(props)
/**
* Bind funtions
*/
const { dispatch } = props
this.patchReservation = params =>
dispatch(ActionCreators.patchReservation(params))
}
Then you just attach e.g. this.patchReservation to onChange -listener. ActionCreators is one of my import's which contains my Redux action -functions.
Cheers!
Im trying to use some Object Pattern in React Components because the usual Component->child structure require often a code rewriting.
class SuperComponentEveryOneWillLove extends React.component
{
constructor(props){
this.state = { master_state_all_will_use : 0 }
this.commonFunction = this.commonFunction.bind(this);
this.getMasterState = this.getMasterState.bind(this);
}
commonFunction() { return do_something; }
getMasterState() { return this.state.master_state_all_will_use }
}
class PoorSon extends SuperComponentEveryOneWillLove
{
constructor(props){
this.state = { for_me_only : 0 }
}
render() {
<span>
{ this.state.master_state_all_will_use } //DOESN'T WORKS
{ this.getMasterState() } //DOESN'T WORKS
{ this.state.for_me_only } //WORKS
{ this.commonFunction() } //WORKS
</span>
}
}
I need to access Parent state and local state.
React allow function super calling but not merging state. I've tried on google to look for some "super" or "parent" keyword to access parent state but it seems it doesn't exists.
At runtime, Son component has no scope of Father's state.
Is this possibile?
I'm not sure if it is what are you looking for, but it's close to it:
class Parent extends React.Component {
constructor(props){
super(props)
this.state = { isParentState: true };
// needed for getting access to parent state
this.getMasterState = this.getMasterState.bind(this)
}
getMasterState(){
return this.state;
}
}
class Enhancer extends Parent {
constructor(props){
super(props);
// get parent state via super keyword
const parentState = super.getMasterState();
this.state = {
isChildState: true,
...parentState
}
}
render() {
return <div>
Merged state: { JSON.stringify(this.state)}
</div>
}
}
Worked example.
Hope it helps
I'm sure it's possible, but you DO NOT want to do this.
Anything you are trying to do with inheritance can be done with composition.
In you case, your "parent component" will pass any information the children may need as props
class Parent extends React.component
{
constructor(props){
this.state = { parentState : 0 }
this.parentFunction= this.commonFunction.bind(this);
}
parentFunction() { console.log("parentFunction()"); }
render() {
return (
<Child
parentFunction={parentFuction}
parentState={this.parentState}
/>
)
}
}
https://reactjs.org/docs/composition-vs-inheritance.html
EDIT
In React, inheritance is almost NEVER the answer.
Now if you're looking for a a way to reuse method logic, why not abstract the method to a helper file?
If that still doesn't work, perhaps a Higher Order Component (HOC) will do the trick.
Here's an example of a simple HOC:
const withCommonFunction = (WrappedComponent) => {
return class extends React.Component {
commonFunction() {
console.log("I'm a common function that is needed in many components!");
}
render() {
return (
<WrappedComponent commonFunction={this.props.commonFunction} />
);
}
}
}
Then you wrap whichever component you want to have the same logic with the HOC.
const Child = withCommenFunction(Child);
This is typically used to help reuse logic that would otherwise be implemented the same in different components
I am using the way below to do the callback as it's said that it's the most optimized/fast way:
class Foo extends React.Component {
constructor() {
super();
this._onClick = this._onClick.bind(this);
}
render() {
return (
<div onClick={this._onClick}>
Hello!
</div>
);
}
_onClick() {
// Do whatever you like, referencing "this" as appropriate
}
}
but what if I need to pass parameters to my _onClick method?
I know how to do it if I used .bind(this) as a prop but the way I showed above i dont konw how to handle that.
By the way, i read the article here but it does apply to me.
I think these articles would clarify a lot:
article1 and articles2. You could try this below implementation also, it's inspired from the 2 articles :
class Foo extends React.Component {
/*
in your case you need to make the bind under the render call as below
*/
_onClick() {
// Do whatever you like, referencing "this" as appropriate
}
render() {
return (
/*
this bind here is necessary to precise the params,
and about the perfermances issues it's very relative to the app composition.
*/
<div onClick={this._onClick.bind(this /*,var1, var2*/)}>Hello!</div>
);
}
}
// a solution for passing properties without
// entring in perfermances issues is to make a small refacto :
class Foo extends React.Component {
_onClick() {
// Do whatever you like, referencing "this" as appropriate
}
render() {
return <MyDiv {...this.props} onItemClick={this._onClick}>Hello!</MyDiv>;
}
}
const MyDiv = React.createClass({
render() {
// Don't need a bind here, since it's just calling
// our own click handler
return (
<div onClick={this.handleClick}>Hello!</div>
);
},
handleClick() {
// Our click handler has access over the this.props,
// since React.createClass auto bounds this.
// so it could just pass what it needs along.
this.props.onItemClick(/*arguments from this.props*/);
}
});
Is there a preference on where you put functions inside a react component? I am still learning React so just trying to figure out the best practices.
class Content extends React.Component {
// What is the difference between putting functions here such as
Hello() {
}
render() {
// or here
Hello() {
}
return() (
<div>blah blah</div>
);
}
}
A function in the render method will be created each render which is a slight performance hit. It's also messy if you put them in the render, which is a much bigger reason, you shouldn't have to scroll through code in render to see the html output. Always put them on the class instead.
For stateless components, it's probably best to keep functions outside of the main function and pass in props instead, otherwise the function will be created each render too. I haven't tested performance so I don't know if this is a micro-optimization but it's worth noting.
Example:
const MyStatelessComponent = ({randomProp}) => (
render() {
doSomething(randomProp);
return <div />
}
);
doSomething = (randomProp) => {
//Do something here
}
It's worth pointing out that there are times when you want to perform intensive calculations in the render() and take the performance hit. Especially when it involves making calculations from props. Take the case of
class Person extends React.Component {
constructor(props) {
super(props);
this.state = {
name: props.firstName + props.lastName,
};
}
render() {
return <div> {this.state.name} </div>;
}
}
Now when props changes, the state won't be updated as the constructor function only runs when the component is mounted. A better way would be to make the calculation in render. So whenever your component rerenders, it recalculates and renders the right value.
class Person extends React.Component {
render() {
const myName = this.props.firstName + this.props.lastName;
return <div> {myName} </div>;
}
}
And this version is a bit cleaner to read:
class Person extends React.Component {
calculateName = () => {
return this.props.firstName + this.props.lastName;
}
render() {
const myName = this.calculateName();
return <div> {myName} </div>;
}
}
I'm wanting to create a React component that does a security check and if that passes it'll render out the children of it, if it fails then it won't render anything.
I've scaffolded out a component like so:
var RolesRequired = React.createClass({
permitted: roles => ...,
render: function () {
if (!this.permitted(this.props.roles)) {
return null;
}
return this.props.children;
}
});
The usage I was planning would be like this:
<RolesRequired roles={['admin']}>
<h1>Welcome to the admin</h1>
<div>
Admin stuff here
</div>
</RolesRequired>
How would you return all the children from the RolesRequired component?
I came up with this solution:
var RolesRequired = React.createClass({
permitted: roles => ...,
render: function () {
if (!this.permitted(this.props.roles)) {
return null;
}
return <div>{this.props.children}</div>;
}
});
What I'm doing is wrapping the children being returned in a <div> but I'm having to add an unwanted/unneeded DOM element to achieve it.
I think higher order components (HOC) are also a good candidate for this. You can basically wrap any component in HOC that defines some behaviour and decides if it should render a wrappe.
Nicest way to do this would be if you're using a ES2015 transpiler with some ES2016 features enabled (namely decorators):
function withRoles(roles) {
return function(Component) {
return class ComponentWithRoles extends React.Component {
constructor(props) {
super(props)
// Not sure where the data to get your roles about current user?
// from but you could potentially to that here if I'm getting your point
// and also setup listeners
this.state = { currentUser: 'admin' }
}
validateRoles() {
// you have access to the ``roles`` variable in this scope
// you can use it to validate them.
return true;
}
render() {
if (this.validateRoles()) {
return <Component {...this.props} />;
)
} else {
return <div>Nope...</div>;
}
}
}
}
}
// You can then use this on any component as a decorator
#withRoles({ showOnlyFor: [ 'admin' ] })
class AdminOnlyComponent extends React.Component {
render() {
return <div> This is secert stuff </div>
}
}
I've used ES2016 features because I think it's nicer to get the point across but you can implement that with just a simple function wrapping, here's a gist by one of the React core members on the topic of HOC:
https://gist.github.com/sebmarkbage/ef0bf1f338a7182b6775