React context not being updated within callback - reactjs

I am subscribing a user to events using pusher-js, and am having an issue with the information I am passing in the callback not staying updated. I use react router and have a 'location' context on my components.
connect() {
let {pusher, channelName, eventName} = this.props;
let pusher_channel = pusher.subscribe(channelName);
pusher_channel.bind(eventName, () => console.log(this.context.location.pathname));
}
For demonstration purposes I am just console logging the current url pathname the user is on when the event comes through. This component gets loaded and stays loaded when the user loads that application. The problem is that, if a user navigates to another page in the app and an event comes in, the pathname does not reflect the actual page the user is on but rather the page the user was on when they initially loaded the app.
Is there a way to keep the callback updated as to any context or prop changes that have occurred?

Updating Context
Don't do it.
React has an API to update context, but it is fundamentally broken and you should not use it.
Read more.
Use React Router's location descriptors instead.

Related

React modal rendering

I've been created a modal that shows on the home page. Modal shows only when U enters the site from a mobile device. It is working well, but I want to have this render only the first time when the site is rendered. Now, whenever I came to the home page it shows.
You can put the modal on the highest parent of the site component tree hierarchy (for example in component) and then use the useEffect hook to make it show up only on the first render of the component like so:
useEffect(() => { ....your logic here that triggers modal open } , []);
Edit:
I see that you mentioned you are only using the state, so if the initialState if on the required state of modal open, then it will be enough to just lift that state up to parent component of the higher component.
Whenever you render some other component it flushes its previous state at component level, There are 2 ways to do that, either you have to use state manager like redux or react's context api and store the state on root level. And if you do not want to show the page even after user closes the browser then consider using local storage.
some references:
Context API
Redux
Local Storage

useContext value not updating

I was trying to use useContext to change the authentication state when a user logs in and this would be received in other components to conditionally show based on whether the user has logged in.
Login Context was setup as below
I passed the provider in this way
I made a button which upon clicking sets loggedIn as true
However, when I re-route to store, the value from useContext still stays as false although I have updated it in the Login component
Upon routing back to "/login" the state from useContext still shows false rather than true
Am I missing something wrt how useContext works?
That's expected. You dispatch your action, but the resulting state will be visible only on the next render phase. Not immediately. It will not happen synchronously. If you want to inspect that value, you can:
React.useEffect(() => {
console.log('loggedIn value changed', state.loggedIn)
}, [state.loggedIn])
I managed to figure out what was happening from another post: useContext does not survive between pages
So, by using react-router-dom and Link the application now works and passes the context to different pages and components but does not survive upon refresh or on opening a new tab.
Note that if this feature is required, for example login/auth, the best way is through localStorage

how to handle subcomponent completion eventsin react / flux / redux

I am designing an application in react/redux and I am new to flux/redux and unidirectional patterns. I ran into a problem which I am not sure how to properly solve within a unidirectional architecture
I want to illustrate the problem with the example of a user registration form that might show up in different parts of the app. Please note that the core problem is about if and where to handle subcomponent completion events and the UserRegistration is just an example.
Let's say I have a component UserRegistration which will render as a form. This component will handle its own submit action which may include some asynchronous calls to a server endpoint and in the end should lead to a modification of the store/state (e.g. adding new user data).
The user flow is the following:
user clicks on 'register' button
user sees registration form
user types in data and clicks 'submit'
user registration form disappears
I want to include this UserRegistration form in different places in the app.
Let's say I want to show the registration form based on a route /register and after succesfully registering I want to route back to /.
The intuitive thing for me to do (coming from a non-unidirectional world) would look something like this
function MyApp() {
const isRegisterRoute = //... somehow check if /register is active
return (
<button onClick={ () => { routeTo('/register') }}>register</button>
{
isRegisterRoute && (
<UserRegistration // handles actual registration internally (network calls and store modification)
onCompletion={ () => { routeTo('/' } } // pass completion handler which will route back to initial path
/>
)
}
)
}
This would solve the problem but I am wondering if having a callback for such a component with a complex flow is an anti pattern in a unidirectional architecture.
One concern is that the callback basically inverts the direction and it's no longer unidirectional.
Another concern is that I would have to pass the onCompletion handler down the chain within my component so it gets executed once the registration is complete. This passing around of the handler does not feel clean as it leaks into a lot of places.
On the other hand I don't want to handle the routing back to '/' inside the UserRegistration component as the success route or action might be different depending on where I use it so I want that logic to be decoupled from the component.
What would be the appropriate/best-practice solution for the problem described above within flux?
It's not data flow at all
It's not an anti-pattern as I don't see any data flow from sub-component to parent, like
<SubComponent onComplete={data=>this.setState({data})}/> // not good
reroute to another router is logic, the next router is the property passed to UserRegistration component, so it's the same as
<UserRegistration nextRouteOnComplete="/"/> // property
and handle routeTo logic in UserRegistration.
A function can be dynamic, do make sure no data will be passed to the callback function, the callback is designed to handle logics after complete, no data should be passed, and data update should follow the unidirectional data flow,
dispatch action -> reduce action -> mutate state -> rerender

react old state is showing data in new url page?

I have List page where list of posts are displaying by calling the action in componentDidMount method. Links are also displayed so that when user click it will show that particular post. But when new page/url is rendered it shows the list of all posts without fetching, but when we refresh the page it does not show the list. What it means that the state data is visible to new page.
How it occurs because in react state clears when url is changed ?
enter image description here
How it occurs because in react state clears when URL is changed?
This is true and not true, actually depends on what context you are looking at. In here react state(the component state will clear) when the component is unmounted or when you deliberately.
So possible places you should look at it are:
check whether you are checking somewhere that data is fetched and you don't need to make the call. some flag in your reducer that is not being reset.
Are you using any kind of data persistence, while reloading? like saving in session storage or local storage.
Try to add debugger in componentDidMount and this.props.fetchPost function and see if those are being called

React Router: Transition without window.location

I have an application that uses React Router. The application creates a new item by calling the createPage action, which calls my RefluxJS store and makes a call to an API endpoint. Once that API call returns and is successful I pass the new page object to the pageCreated action. Within my onChanged even in the JSX file I want to transition to a route based on a property of the page without refreshing the page, but I am at a loss on how to do it.
I want to do something similar to window.location = /pages/1234 where 1234 comes from the page object returned by the API.
I have tried Router.transitionTo('/ua-manager/pages/' + options.alias);, but that returns as not a function. How can I achieve this transition without using window.location?
#transitionTo exists on the Router object instance and not the class so access it through this.context.router and it'll work or just add the Navigation mixin.
this.context.router.transitionTo('/ua-manager/pages' + options.alias);

Resources