In ember I could write something like this:
statusChanged(){
//...do some code
}.observes('observableProperty')
What is the right way to do the similar work in React.js?
You can do your logic in component lifecycle methods
componentWillMount, componentWillReceiveProps and others.
Whenever you pass new props to a component it will run throutg lifecycle.
Read more about it
Alternatively you can use Rx.js. But conceptually I dont think it is a correct approach. React implies you to manipulate props and states of a component and handle all logic in lifecycle or in synthetic events.
Related
Is this possible And how to do this. I worked on a similar thing in vuejs like
this.$emit("send",payload)
and then listen in another component
this.$on("send",(payload) => {
/and do something the in another component
}
How to Do this in ReactJS
you can use a react context https://reactjs.org/docs/context.html
or redux https://redux.js.org/
What you want is called event bus in vue.js, but it is an anti-pattern so it was removed from the API in vue 3.
However if you really liked that approach, you can probably achieve it with an external library that implements the event emitter interface.
You can read more about it here with provided example: https://v3-migration.vuejs.org/breaking-changes/events-api.html#event-bus
This question is about internals for partial re-renderings with React-Redux.
To explain what I mean, I will first introduce a very crude technique for managing state without any state management libary.
The technique uses a a huge "AppState"-object that is owned by the top-level App-component.
Suppose that this AppState holds not only state-properties, but also several callbacks that mutate those state-properties.
Furthermore, suppose that we use props to pass down this AppState throughout the entire component hierarchy.
Thanks to the ES6-spread syntax, passing a huge number of props can be done without a lot of boilerplate code.
In the top-level App-component, it will look like this:
<ChildComponent {...this.state} />
In all other components, it will look like this:
<GrandChildComponent {...this.props} />
It is important to note that the ES6-spread syntax does not actually pass the AppState-object. Instead, it extracts all the AppState-properties and passes them as separate props.
Now we should distinguish between top-level properties and nested child-properties of the AppState:
If I mutate a top-level property of this AppState by calling setState, then the entire app will re-render (unless I use things like pure components).
However, if I change a nested child-property of this AppState, then nothing will happen because React does not notice the property change.
This leads to my final questions:
What is the render-performance of this crude approach in comparison to Redux?
How exactly does Redux handle "partial renderings", such that only some of the Components re-render after a state mutation?
If I mutate a top-level property of this AppState by calling setState, then the entire app will re-render (because everything depends on the AppState).
If you mutate and use pure components then nothing will render, you change state by creating a new state object.
However, if I mutate a nested child-property of this AppState, then nothing will happen because React does not notice the property change.
This is only true if you mutate and components are pure.
What is the render-performance of this crude approach in comparison to Redux?
Prop drilling will re render the entire tree but branches that use state that didn't change won't re render if they are pure. Prop drilling is bad for maintenance because if you need to refactor grand child state logic you may need to refactor the whole tree or branch. But from a performance point it would not take a big hit provided that you use pure components and are careful when passing callbacks and not re creating them on every render (see useCallback).
How exactly does Redux handle "partial renderings", such that only some of the Components re-render after a state mutation?
React-redux useSelector or connect mapStateToProps are always called every time dispatch changed state and before rendering.
If the result is different than last result then react-redux will trigger render of the component. If the component gets props then a render could also be triggered because props change and mapstate/selector will be executed.
A connected component will observe state and render when the result of mapState or selector has changed. An example app with logs showing what react-redux will execute can be found here
For state management, you don't necessarily have to use Redux, if your use cases are small, maybe React Hook would be perfect for you.
For React rerendering matter, what I know is there are several strategies (useMemo, PureComponents) provided by React for managing and improve the performance. It really depends on how you manage your components.
One example is using PureComponent, even if you have a large state in your top-level app.js, if you manage the child components properly, they will not re-render if their receiving props haven't changed.
I have always made API's request in ComponentDidMount lifecycle and called setState in the callback. But while digging deep I happened to find out We should not call setState in this lifecycle as it triggers render method again and React also doesn't recommend that.
Then in that case where exactly we should make that request and call setState to use result after that?
You should absolutely make an API call in componentDidMount. What is not recommended is to re-render a big component, instead what you should do is break your UI into small logical components and only re-render only what is needed , not a whole. For example, you have a big component named HomeComponent which has 3 small components called NavComponent, BodyComponent and FooterComponent. You should NOT be calling the API from the componentDidMount of the HomeComponent since calling setState from HomeComponent will re-render all the small components inside HomeComponent, which is not necessary since you know that the navbar or footer is not needed to be re-rendered. Rather from the BodyComponent, because only the body part needs to be re-rendered since its state has changed. So you should be calling the API from the componentDidMount of the BodyComponent, that way you re-render only whats needed.
#Shababb Karim is right but if i were to implement API calls in my project i would add a state management library. Redux is a great way to implement a global state to the app where you can set data from said API. All components that need that data can be attached to the Redux state to get it.
Redux can be a bit of overhead in smaller projects though. In this case there are other options like Flux (although i like Redux more).
I have a react component which i am injecting a mobx store. when I try to access an observable from my store inside a lifecycle method (componentWillMount or componentDidMOunt) the value is empty. however when I access it inside the render method it is available. Is there something I am missing? I feel like I'm missing something basic here.
The documentation clearly states that observer from mobx-react tracks observables only in render method of wrapped component.
Function (and decorator) that converts a React component definition,
React component class or stand-alone render function into a reactive
component, which tracks which observables are used by render and
automatically re-renders the component when one of these values
changes.
If you take a look at observer sources you can confirm that it only tracks render method
Hi by my experience with Mobx state management you should not access the
observalbe variables from React Component.
Even when you inject the Redux Store into React Component. (Decorate or wrap).
The computed variables are designed to provide updated observable variables to React Component.
You can access Mobx actions and computed but not the observable. They are used only inside Mobx class.
I'm fairly new to React and I'm trying to understand a clean way for child components to communicate with each other.
In a simple component, I know that I can make use of props to pass data to child and callbacks for children to pass data back to parent component.
In a slightly more complex case, when I have multiple children components in a parent component, the communication between the children gets a little confusing. I'm not sure what I should do for children components of the same level to communicate with each other.
In my case, I decided that, maybe, I could use states. So I will have a state value in the parent component, and pass it on the children's props. Similarly, the callback handlers (called from the children component) in the parent component will help to set the states accordingly so that a state value gets passed on from one child to another through React's binding.
And a pseudo code could look something like:
//Inside Parent Component
constructor() {
//initialise state for the child components
this.setState({testList: []});
}
render() {
return (
<div>
<ChildA onSomething={this.onSomethingHandler} testList={this.state.testList} />
<ChildB onSomethingElse={this.onSomethingElseHandler} testList={this.state.testList} />
</div>
);
}
onSomethingHandler(evt):void {
if(blah.blah.blah) this.setState({testList: this.state.testList.splice().push(evt.value)};
}
onSomethingElseHandler(evt):void {
//Some other complex biz logic...
if(blah.blah.blah) this.setState({testList: this.state.testList.splice().push(somethingOtherStuffDueToLogic)};
}
//Inside ChildA Component
export IChildAProps {
onSomething: (evt)=>void
}
render() {
//Do some logic from the value in testList property
if(this.state.testList == blah blah)...
return (
<button onClick={this.props.onSomething({id:321, value:"wassup! I'm ChildA."})}>ChildA</button>
)
}
//Inside ChildB Component
export IChildBProps {
onSomethingElse: (evt)=>void
}
render() {
//Do some logic from the value in testList property
if(this.state.testList == blah blah)...
return (
<button onClick={this.props.onSomething({id:123, value:"yo! I'm ChildB."})}>ChildB</button>
)
}
At this point, I'm starting to wonder if the logic in that 2 handler methods, namely onSomethingHandler() and onSomethingElseHandler() in the Parent component, should actually be resided inside the child components themselves? I thought of this because those logic look like something the child component should be handling on their own to serve their purpose. The parent component shouldn't do it for them or it might just grow messy. But I've no choice because of how I'm handling their communication. Apart from this, I also created a new state simply just to allow them to communicate.
So far, this is still relatively manageable. But in my own experiment, it has got to a stage where I've children component nested inside another children components that need to communicate across other children components of the same (or sometimes different) level. Using states for communication also meant that I have many states all over the place, which doesn't look like a good idea to me. And the parent components ended up with tons of messy callback handler methods to manage all that propagation of data up and down the component tree.
The situation is so messy that I can at most illustrate it as something like so:
And you can see in the above illustration, ChildB ended up having yet another state just to help passing that information between its children components.
I'm sure I'm missing something that I should know about React. The callbacks I'm having in the parent components seem a little too much just to handle data propagation. How should I really organise the communication of children components in a clean and maintainable way?
Every React programmer hits this wall at some point in time. I did too. The answer is to use Redux for state management. You have experienced how tedious it is to use React's native state.
Redux is a state management mechanism which can be used in conjunction with React. So you won't be using React's state, instead you will use Redux.
Redux provides a single store, where the state of entire application is stored. You can access the state in your components using connect() method.
But there is a caveat. Not all of the react components are connected to the Redux store. There are two types of components-
Smart/connected components: Connected to redux store
Dumb components: Dependent on connected components
The idea is to pass the state from redux store to Connected components via React's props. The connected components can directly consume state from the store. The dumb components are not directly connected to the redux store. The connected components also pass the state to the dumb components via props. So you see, React's state is bypassed altogether. Now, if you want to change the state, following events must happen-
An event is fired from the smart/dumb component.
Actions are dispatched to the store
Reducers create a new state according to the actions.
A new state will be stored in the store.
Store will return new state to the connected components via connect() through props
Dumb components will receive new state from connected components through props
What are actions and reducers?
Actions are nothing but javascript objects that describe how to change the state.
Reducer is a "pure" function which builds and returns the new state tree according to the action dispatched to the store.
Redux - http://redux.js.org/
Redux-thunk - https://github.com/gaearon/redux-thunk
Redux-saga - https://github.com/yelouafi/redux-saga
Most fashion way is using Redux.js (or flux.js) to matain your child components state.
http://redux.js.org/
If you don't like invoke third party js. You can use refs property:
https://facebook.github.io/react/docs/more-about-refs.html
We can use the react context API,
Context provides a way to pass data through the component tree without having to pass props down manually at every level
Also, note that Mark Erikson has mentioned in his blog,
Yes, the new context API is going to be great for passing down data to deeply nested components - that's exactly what it was designed for.
If you're only using Redux to avoid passing down props, context could replace Redux - but then you probably didn't need Redux in the first place.
Context also doesn't give you anything like the Redux DevTools, the ability to trace your state updates, middleware to add centralized application logic, and other powerful capabilities that Redux enables.
To handle scenarios you mentioned, context API is a good option and you don't have to use additional libraries for that.