React / Redux Topic: Conditional Rendering based on Store State - reactjs

Preface:
This is an authentication mechanism in my project.
I am refactoring from using Contexts to Redux to control state
The Redux store holds a "isLogged" as a boolean as a part of the state. Upon successful login (the user submits the form with the correct email and password), an axios response validates the user and the client dispatches an action with a state change. The state change happens successfully, based on what I see using the redux dev tools extension.
The Problem:
I have a navbar component that conditionally renders links public and private components based on the isLogged state. It just doesn't rerender when the store state is updated, so currently the user is not able to see an updated navbar, even though the state change happens as it should.
Thank you in advance for your help.

I just solved the problem.
I had to access the store state via the useSelector hook from "react-redux". It seems that when I was trying to just grab the state earlier using the store.getState() method and storing it in a variable and passed down through props, the function components were not listening to the updates.

Related

How to stop Redux resets state when using window.open to redirect a URL

I have a simple login page, when the informations are correct, I redirect the user to another url via window.open() with _self parameter. Eg: window.open("/home", "_self");
The problem is, I save this login information to the Redux store, but naturally Redux resets the store because of window.open()'s page load. I can't use Link on Login button.
So is it possible to redirect to another URL without page load (not using Link as I mentioned) or avoid Redux reset state action?
You might want to use Redux Persist which allows you to store your redux state in the local storage of your device and when your react app renders initially hydrate your redux from the redux persist OR you can pass in query param that indicates somethings like
yourURL.com?isLoggedIn=true
and trap in the query param and render your component as needed.
Hope this helps.
I had to solve it via Link, giving to parameter's value with ternary operator.

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

When do I choose React state Vs Redux Store

I've been learning Redux and a part I'm unclear of is, how do I make a determination between using react state vs redux store and then dispatching actions. from my reading so far it looks like I could use React state in place of Redux store and still get things done. I understand the separation of concerns with using Redux store and just having 1 container component and the rest of it as stateless component but how do I make the determination of when to use React state Vs redux store is not very clear to me. Can someone please help?
Thanks!
If the state doesn't need to be shared with other components, or the state doesn't need to be keep when the component is unmounted, then you can just put it in the component's state.
You can think that the Redux store is the database of front-end, if you have something like product data fetched from an API, then the Redux store is the right place; if you have a dropdown component, which takes a isOpen prop, then the parent of that dropdown can just keep dropdownIsOpen as a component state.
For more information, here is the answer from Dan: https://github.com/reactjs/redux/issues/1287
Also you said
only 1 container component and the rest of it as stateless component
This is incorrect. You can have several container components. A container component can also contain another container component.
From book:
First of all, we should always keep in mind that only the minimal
amount of data needed should be put into the state. For example, if we
have to change a label when a button is clicked we should not store
the text of the label, but we should only save a Boolean flag that
tells us if the button has been clicked or not. Secondly, we should
add to the state only the values that we want to update when an event
happens, and for which we want to make the component re-render.
Another way to figure out whether the state is the right place to
store information is to check if the data we are persisting is needed
outside the component itself or by its children. If multiple
components need to keep track of the same information, we should
consider using a state manager like Redux at the application level.
There are a few things that need to be grasp
State of component: If you want to keep state-specific to your HOC then use state. Now in the function component, we use useState.
State of redux: If you want to share data throughout the application use redux state.
Store of redux: It's nothing but a database for the redux library. In the case of redux, we can have only one store. To use multiple stores we can use Flux but it will make things more complicated.
You're absolutely right. Redux (and flux architecture in general) are only formalism tools to help for building large apps. They're not necessary at all.
There's actually an interesting post called You might not need redux by Dan Abramov, the creator of redux that might give you a better answer than I do: https://medium.com/#dan_abramov/you-might-not-need-redux-be46360cf367#.7093fm1z8
If state is needed only for that particular component then prefer to use react state.
For example using state for UI actions
If any state you want to use across the component/project then go with redux state.
For example API response data etc
For detail understanding refer this link
https://spin.atomicobject.com/2017/06/07/react-state-vs-redux-state/

How to get state value back to clicked button inside mapdispatchtoprops?

I am new in react and redux. I have a button on a component on click of that I am calling api and set the response as state. But I want that state back to clicked function where on base of that state I want some conditional work.
I dont think how to implement this.
Thanks,
Vijay
You need to use Connect.
Connects a React component to a Redux store.
It does not modify the component class passed to it.
Instead, it returns a new, connected component class, for you to use.
You need to use mapDispatchToProps so that your data is back to you at the component once fetched/retrieved making the component re-rendered, and that's what you need and that's the killing feature of Redux uni-directional flow archticeture.

SPA + back button + form state

I am converting a jsp multi-page app(mpa) into a React single-page app (spa). In the mpa, the back button worked and the form retained its state.
In my new React app, the back button works but the form does not retain its state.
Question: is there a trick to make my form retain its state after "backing" to it (in an spa).
Here are the two solutions I came up with:
Encode the entire form state into the url. Then update the browser history with an updated url every time the form changes. But, this seems like a huge pain in the butt.
Modify the structure of my app such that the form in question (a React Component) stays mounted (and just use the css visibility or display property to show and hide). But, in a large app, leaving every page mounted in the DOM seems like it might lead to performance problems.
By the way, I am using popstate and the browser history api to achieve SPA behavior (i.e. i have rolled my own router) as described here.
Hopefully someone can propose a solution that is better than my two solutions. Thanks.
I ended up using something similar to Wylie Кулик's answer with a few changes:
I didn't want to switch to Redux for just this one use-case. So I used the component state of my top-level component (i.e. a component higher up the tree).
I cached the form's state on the form component's componentWillUnmount and restored the cached state on componentDidMount.
I passed the cached state as a prop from the higher component to the child component.
It ended up being a very small amount of code and is working like a charm so far.
Use Redux to have a state store which transcends any particular component. Then in your component, as part of the form submission process, dispatch an action with payload of all of the form data. This should be cached on state and then when the component is remounted by your navigation structure, it should have access to this cache via Reduxsconnectfunctions mapStateToProps method. You can repopulate your form from that.
It's not clear from your question whether or not you are submitting the form in the traditional old way. I would use e.preventDefault in the handler instead, and have all the form data on the component's state, this can be sent to Redux's state store as described above, and Ajaxed off with superagent or similar. At the same time it can be cached.
Redux: http://redux.js.org

Resources