mobx observer not re-rendering when observable changes - reactjs

I'm creating a React Native app and I want to add observable/observer pattern but the observer's render function is not re-executing when the observable changes.
Here is the store where the observable is:
https://github.com/ksairi/GalaApp/blob/development/app/stores/NotificationsStore.js
This is the stores' index file:
https://github.com/ksairi/GalaApp/blob/development/app/stores/index.js
This is the screen where the observer is and this specific line in the render function is the one that should make the render to re-execute again but is not happening.
https://github.com/ksairi/GalaApp/blob/development/app/screens/Notifications.js#L86
Any ideas?

Related

In React, how to encapsulate logic in a Todo component?

In a Todo app made with React, like this one, we have a function toggleTaskCompleted in the App component which gets passed as a prop to each Todo component. This function can then be called in the Todo component when a button is clicked resp. a checkbox is toggled.
I wonder if we can move this logic entirely to the Todo component. For example, this is possible in Svelte and Vue. In Vue, we create a ref for the list (and in Svelte, a regular variable), loop through it to list all todos and pass the respective todo as a prop. When we change the todo in the Todo component (for example, mark it as complete), this change is automatically also seen by the parent App component. (Meanwhile, the approach by passing a function as a prop is also possible in Svelte and Vue.)
I prefer this approach much more, it is more encapsulated, and we have to write less code. So I wonder if we can do the same in React.
Edit. Actually, the list is updated in the App component. However, this does not effect a rerender, and also useEffect, depending on the list, won't notice this change. So my question is basically how to inform the component about this change (without writing too much code or even using external state mangement).
I guess it would be better to use React Context in this case because you'll need to applay the state and the logic for your Todos in many components (like a navbar to track number of todos ...) . In this case React Context is a way to manage state globally. So it allow your components to access some global data (In your case your todos and the function toggleTaskCompleted ) and and re-render when that global data is changed . this is a simple Demo how to use it

Reactjs MobX observer re-render target

I'm new to react, and I've just started using state management tool Mobx. I am reading info about mobx here and there, but there are few concepts that I do not understand.
I know react re-renders every time if local state is altered using setState. It's re-rendering target is the component in which its local state has changed(am I right?). But for mobx, when the store's observable property has been changed by the action in an component, I'm not sure which component gets re-rendered here because this changed property is not 'local' as the example above.
So for example, If I alter an observable property defined in class CityStore in a component called city(assume that I have other components as well), then which components will get re-rendered? does city component gets re-renders because I have altered the observable property there? or does all the components using that observable property gets re-rendered? I would like to know the mechanism of re-rendering of components with #observer decoration.
Created mobx store is passed on by using provider and #inject. I'm not quite sure what #inject does. If I wish to use store called cityStore in city component, I do follows:<Provider city = {cityStore}> <city/> </Provider>
Then component city and all its child component can access and alter cityStore. then why do i have to seperately put #inject for every component that wishes to use cityStore if I have already used provider? is it just the syntax, so provider and #inject always has to go together? So for example, if I called <Provider city = {cityStore}> <city/> </Provider> on parent component city and do not put #inject for some child components of city component, that component will not be able to access cityStore?
Question description is a little long, but I will be really appreciated to know the answers thank you!

React + Redux: Scrolling a DOM element after state change

New to Redux here, really just looking for a "best practice" answer.
I am building a chat application using React + Redux. My app looks something like this:
3 stateless components for my app container, message list, and input bar
Actions for adding user messages/responses
A reducer that takes in these actions and returns a messages array
Chat middleware which handles a emitting a socket message when then ADD_MESSAGE action is dispatched
So far so good. Everything is working well, however I'm unsure of how/where in this sequence I should be making DOM manipulations. Specifically, I would like to scroll to the bottom of my message-list container whenever my messages state changes.
All I need to fire is something like: messagesListElement.scrollTop = messagesListElement.scrollHeight;, but not sure where the appropriate place to do this is.
You mentioned that all the three components are stateless which means the messages are maintained in redux store which means they are passed as props to the child components. Basically there are five life cycle methods which could get triggered after/before the component gets updated.
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
componentDidUpdate()
render()
Now since you want to scroll down after a new message is pushed to the messages state, the best place to do this would be componentDidUpdate()
Why not componentWillReceiveProps - This is the function which will get executed just before a new message is about to be passed in the new props of the component. This is the best place to update your component's state against the new props but since your component is stateless, this is not the right place for scrolling. This could be helpful
Hope it helps :)

Refresh logic in react component or flux/redux?

So i'm fairly new to React and I can't wrap my head around a concept on how to re-render a main component based on another component.
Lets say we have a to-do application and a to-do item can have a state (new, running, closed). We are displaying all to-do items in a list and we can filter the items based on their state. We are using a bootstrap dropdownbutton like component to set the filter, which is a React component. Now when we change the filter we obviously want to refresh the to-do items.
My question is, does the logic of the selected state belong in Flux/Redux or does the filter component just say "refresh your items" to the main component?
When you use Redux in React application, follow one simple rule - all your components are stateless (means, no component initializes its state or calls .setState() anywhere).
The redux way of design based on state container, one big object that holds all application state. As React component, being connected to Redux store, Redux will pass the state (or portion of it) into that component, as this.props.state property.
That high-order component (or smart component), renders its children components (or dumb components) and handles events from them.
If child component requires change, it triggers corresponding handler (which typically passed as props). The only way to change the state is to dispatch an action. That action contains a type and a payload and based on that type, corresponding reducer is selected. The reducer then produces a new state, based on previous state and action payload.
If in the result of reducer call, state got changed, Redux will re-render high-order component, passing new state in properties. So, all child components will be updated correspondingly.
Check this example and trace how AddTodo component calls .handleClick() and then upper to .onAddClick() which dispatches an action.
If you are using redux, then on your dropdown you should have an onchange handler that dispatches an action every time the value is changed with the selected state (new, running, closed).
Redux reducer will handle this action by changing some state accordingly in the store for example: display = 'completed'. In addition to this, your todo list should also be stored in the store and it will likely be an array.
Your react component should receive a the todo array and display as props, and therefore everytime any prop (todo array or display) change, it will trigger a re-render.
In this case, your component should only display those todos that are complete (i.e. in the render you check if the state of each todo === this.props.display.
So to answer your question: redux keeps the state of the dropdown, which is passed to your main component, your main component then render only the todo's that matches the criteria.
So in a very minimal way, you could pass a function down to the select box, which calls setState on the top-level component. When that state changes, it will re-render its child components. This pattern doesn't scale well, and leads to the same hell React + Flux is trying to get us away from (state everywhere). I would say, using Flux (or even better, Redux), trigger an action that sets the filter in your store, and use derived data based on the filter state + your list of todo's in the todo list.

How to animate a React component on render?

I am trying to animate a React component that contains data fetched from elsewhere. Placing it in a ReactCSSTransitionGroup worked fine. That is, until I altered the component's render() method to return false until the data has been fetched (to prevent it from being rendered without data).
Now, I guess the component is mounted immediately, at which point the animation classes are added, but only rendered afterwards. Is this thinking correct? How can I get the component to be animated when render returns the actual component?
ReactCSSTransitionGroup activates whenever components are added and deleted to its props.children. Since your component is mounted before you fetch data, nothing will happen after data is fetched (I think this is true even if the component's render() method returns false. Let me know in the comments if that is incorrect)
Here's a solution
Just don't mount the component (in the solution, it's a <div key="1"> tag) until the react class receives the data. Use component states on the parent component to keep track of the state of your asynchronous request.
The ReactCSSTransitionGroup doesn't play nicely with tables as it's default behaviour is to wrap tags with a span element. You can provide it with your own component, but I found the solution quite heavy and complex.
I have a different approach that allows a React component to animate each time its content changes. The animation is continually triggered by toggling between 2 duplicate CSS styles.
Other than the ReactCSSTransitionGroup, another way is to write your own css transitions with an 'enter' class that is added to the component in componentdidmount. Keep in mind that you should change the state in a requestAnimationFrame because otherwise your class would be added in the same event loop as it is mounted, thus wont animate. Here's an example:
https://codesandbox.io/s/zkm5015y1x
Also, more on event loop, a talk by Jake Archibald:
https://www.youtube.com/watch?v=cCOL7MC4Pl0

Resources