Login flow with ExNavigator and Redux? - reactjs

I'm working a React Native app using ExNavigator and I want to use Redux. I want a basic login flow, by which I mean:
User clicks "Log in" with correct info
Redux does a usual async flow through redux-thunk or something
When the user is logged in/request was successful, move to Profile route
I've done Redux login in the web, but I am sort of confused as to how to move ExNavigator to the Profile route when the login works because the Navigator object seems to be contained completely in the components and not Redux.
Any pointers?

A pattern I use often is detecting state changes in my component's componentWillReceiveProps, and triggering the navigation transition from there.
Let's say your state contains a property isLoggedIn, which you set to true when the login is successful. The property is also passed as a prop to your component. You can then:
componenWillReceiveProps({isLoggedIn}) {
if (isLoggedIn && !this.props.isLoggedIn) {
this.props.navigator.push(nextRoute());
}
}
This might not be the most elegant way of solving the problem, but it works. The React Native Navigator, and consequently ExNavigator built on top of it, does not lend it self easily to the Redux architecture.
React Native team is working on a new navigation API, currently known as NavigationExperimental, which ships with latest versions of RN. It works nicely with Redux (example), but as its name indicate, it's still very much experimental.

Related

Presentation component is getting cached while moving between screens

I am building a react-native app, in which all screens share the same generic functionality like
1. Making ajax requests
2. convert snake_case keys to camelCase
3. show loading indicator while fetching data
4. subscribe to redux store and expose store as props
here are the tools I am using
react-native
expo
redux
react-redux
react-navigation
My container has no idea what urls to fetch because it is used with all the components. I am calling the container component in this way
const fetchUrls = store => return [url, url];
return MycontainerComponent(WrapperComponent)(fetchUrls);
this seems to work fine on initial load, but didn't work when visiting a screen, navigate to another and come back to the first screen again. Its as if components are cached and not recomputed again. this is for me as long as no data in the store changed. so I wrote a watcher inside the container component and to see if any value in the store changes, the component will re-render. but then this worked fine until I had one more problem.
I want to support user switch like in gmail because mine is a parent app and a parent can have 2 or more children studying at the same school and u can understand the rest.
Now when I am switching the user, I updated the redux store and I thought it would re-render stuff and it would be all fine. Until I hit with reality.
When I switch user, it seems as if the component is trying to unmount and fetch urls for new store values at the same time and react complaints with typical "don't setstate in the componentwillunmount, its a no-op, unsubscribe etc."
I have no idea what's happening, can anyone shed some light on this. Thanks.
With a stack Navigator the screens are not unmounted after they lose focus. This is a performance optimization. If you want to execute logic when a screen regains focus put your logic in NavigationEvents onWillFocus or onDidFocus.

Is it wrong to wish for Redux-driven routing, and route/URL as second class citizen?

I have read the official Redux documentation regarding React Router and investigated react-router-redux, redux-router and redux-little-router. I also agree with the rational for redux-little-router: React Router has strong architecture consequences on a React app, and they somehow conflict with Redux.
My feeling about routing is that it has too much importance in the React+Redux ecosystem, whereas it should be treated as a second class citizen. When designing a single page app, we often don't need URLs at all. We still support them to preserve the Web experience (SEO, bookmarking...), but we certainly don't want them to drive the app structure.
What I am thinking of:
External navigation: a route-to-state mapping, with the classic reduced action mechanism. In other words, navigation triggers an action that is dispatched and processed by a custom reducer (with just some help for route mapping and parsing). Once the state is updated, this is React as usual. In particular, there is no mapping between routes and React components, unlike what React Router's Route does and a bit like redux-little-router does.
In app navigation: the current URL is derived from the state, a bit like the view. A kind of renderURL function a Redux middleware is aware of. If a state update generates no change in the URL, well, nothing happens. But if the URL is now different, the middleware reflects the change by pushing it to the history.
With this approach, there is no more Link component. There are only regular Redux actions and a middleware to take care of the navigation as a side effect. Actually, this solution does for navigation what React does for the DOM: a (super-straightforward) URL reconciliation, with the state as the single source of truth.
To illustrate this, consider the Redux Todo list example:
When visiting /SHOW_ALL, an action containing the URL is dispatched. A regular, navigation-dedicated reducer sets visibilityFilter to VisibilityFilters.SHOW_ALL in the state, possibly with some route mapping/parsing helpers. As an alternative, the navigation action could be turned into a SET_VISIBILITY_FILTER action, which is then dispatched and reduced as usual.
A fancy renderURL function is registered at store creation as part of a middleware. It returns "/" + state.visibilityFilter. Again, some route management helpers would be welcome for real life apps.
Now there is no change in the original Todo app. We only add some new code to support a new feature.
The problem is: I can't find anything that support this vision. No article, no react-redux-something package. As a React beginner, either I am a genius or there is something I don't get. Since the later is the most likely (to my uttermost dismay), I would appreciate:
Feedback regarding the "Redux-driven React routing", or whatever it should be named. How is it flawed?
Hints about how I should consider Redux and routing, like relevant articles.

Expected behaviour for redux state on page change

I have a React app, using Redux & Redux Sagas.
Currently I have a fairly standard search page as in :
User enters value via form input, magic happens behind the scenes, an api is consumed and my redux store is populated with the results.
These results are then surfaced via the view layer.
Using React Router 4, if I then navigate away to another page, on returning to the search page, my previous results are still shown. I guess this is expected as my redux state still contains this data.
My Questions is should this state be cleared on navigate away? I am very new to Redux / React / React Router and am trying to understand if I have implemented this correctly or in fact unless I instruct the store to clear that state, it should persist.
tl:dr
Should a redux store be cleared if I navigate away from the page or is it ok to leave that data on the view?
Using React Router 4, if I then navigate away to another page, on
returning to the search page, my previous results are still shown
In React & Redux epoch you web application is SPA, and tools like isomorphic react-router-dom helps with this task, including seamless SSR support for URL router.
Of course, you can use react-router-redux instead, and in this case navigation to different pages will appear as actions, so them can be catched in saga, and then load new initialstate for redux store.
Library and example can be found here: https://github.com/jfairbank/redux-saga-router

when use redux, can I call api in container component?

I am very confused recently.
When I write redux, if I have to call api ,I will put an action to update reducer, the component just render the data from props
But recently I see my coworker just call api in container component and then update the component state.
He says if your data do not need to share with other component, you can call api in component, so you don't have to write so many code in actions and reducers.
I thought this is very convenient. For example: If I have a feature : When user click the button, I have to send an email.
This feature do not need to update store by reducer, just have to alert "send success"
So I can write this code in container component:
async onClick() {
// 1. call api
const {error, response} = await sendMail({email: this.state.email});
if (response){
// 2. alert success
this.setState({
modal: {
show: true,
}
});
}
}
But I don't know if this match redux's principle.
Can I call api directly in component if the state do not need to share with other component??
You can call api from dispatched actions or from React components: it is your choice to make. There is no mandatory rules here and it depends on what you want to do with your components:
When to use React states:
It is better to have smart component handling their own state because it ease the integration in external projects. Having a component that uses Redux means a project needs to add the requires reducers to use the component.
If a component handles information not required by any other components, use React state. It is often the case for information related to UI state.
When using Redux reduces:
If you need to test your component, prefer Redux because you'll be able to connect "test actions" to your component when testing them.
If you need to share a bundle of data through components, prefer Redux to mutualise information.
This question has been treated by Gaeron on Redux github repository if you want to have a look. He explains:
Use React for ephemeral state that doesn't matter to the app globally and doesn't mutate in complex ways. For example, a toggle in some UI element, a form input state. Use Redux for state that matters globally or is mutated in complex ways. For example, cached users, or a post draft. Sometimes you'll want to move from Redux state to React state (when storing something in Redux gets awkward) or the other way around (when more components need to have access to some state that used to be local). The rule of thumb is: do whatever is less awkward.
I suggest you have a look at classux

Controlling Page State With re-base or reactfire

currently looking in to making a new web app with Firebase, React and re-base or reactfire. I understand that Flux when used with Firebase does not make complete sense, and they don't work well together. My question is, if I do not use Flux or Redux, but instead just re-base or reactfire how do I control the page's state? For instance, knowing a drop down is active.
IMO, knowing a drop-down is active is perfectly managed by using React, without the use of redux or flux and regardless of what backend you are using.
For example (and I'm making some assumptions here what functionality you want precisely):
Set your initial state to { ddActive: false }
Then setState({ ddActive: true }) on clicking the dropdown button
Then, on clicking anywhere, setState({ ddActive: false }) again
Hope this helps!

Resources