How to keep props data persisted in Vue? - javascript

I have an application that is simplified into 4 Vue components:
TextbookSelection
TextbookView
ChapterView
Textbook Header
In my TextbookSelection component, I make an API call to retrieve all my available textbooks from my database. I then populate the front end with the data and dynamically create router links that will take the user to the next vue component, TextbookView if they click on one of them. I pass in a textbook data object as a prop that contains info about this textbook so that the TextbookView component can use it to populate instead of calling for the textbook data again.
In my TextbookSelection.vue, these router-links are created.
<router-link
:to="{
name: 'TextbookView',
params: { textbook: textbook},
}"
In my TextbookView, I have props: ["textbook"] written. I also have a TextbookHeader component in there that displays all the info about the selected textbook, so I pass in the textbook data in as a prop to the TextbookHeadercomponent as well. I have this as a separate vue component because I want the header to persist as the user goes further into the textbook, such as the ChapterView component. So as you can see, I am taking the same textbook data object I received from my first component (TextbookSelection) and passing it into every component if the user goes deeper into the textbook.
This works on the first pass; the user can select a textbook and it displays all the correct textbook information in the header. But then problem arises when the user hits "back" in their browser, or if they refresh the page. Suddenly, the header disappears because the prop data (Textbook data object) is now missing.
Error in render: "TypeError: Cannot read property 'id' of undefined"
found in
---> <TextbookHeaderView> at src/components/TextbookHeader.vue
<ChapterView> at src/components/ChapterView.vue
<App> at src/App.vue
How should I approach this problem? I don't know if what I'm doing is the correct way or not, but basically what I'd like is:
Have a header vue component
Have textbook data be persisted (user can go back and forth/refresh and the header will still have correct info)
Not have to constantly pull in data whenever the header component is created

I would recommend you use VueX for state management.
You could have an action that fetches your data from the database upon the creation of your home component and then update the store according to the fetched data.
This allows all your components to have access to your data that is persisted through routing.
Your TextbookHeader and all other components then have a single source of truth (the Store) and you don't have to re-fetch data (which you shouldn't anyway).
For more information on Vuex, please visit the official documentation

Related

Persist sidebar with fetched data through all the routes

Overview:
I got this route in my react application
example.com/routeName/:id
This is the entrypoint for my users, they click on the link and see a screen with informations provided by this hash in a right sidebar component.
example.com/routeName/94a31bb9-e6ae-4e9a-8749-0807f9efd0001
Below I attached a kind of wireframe, trying to be more clear about the sidebar:
Wireframe to understand how my app components are shown at the end, and why the hash is important in a visual way
This works fine, I can get the hash and make the request inside my dumb component to display data.
The problem:
I'm doing the fetch to the api in my Layout component, and passing down the data via props to my sidebar that is fixed in my layout, because it is displayed through all the user experience
When my user sign in, my route change, from:
example.com/routeName/94a31bb9-e6ae-4e9a-8749-0807f9efd0001
to:
example.com/nextRouteNameHere
I still see the component with the information I need, but if I refresh the page at the second route, the app crashes, because my sidebar cant find the hash to fetch my api and get the necessary data.
What I've been trying to do:
Persist this route with the hash and make the route change internally - but that doesn't makes sense to me at all, and I could not find any resources even close to this strategy.
Persist this hash in localstorage and get the hash with hooks inside the sidebar. This way if I can't find my hash at the url it'll be in the localstorage and I can fetch my api to get the data. I did it, but doesn't work because the components presents the some behavior, trying to render with no data.
As I'm using redux to manage the global state I've already taken the hash and the fetch response to the localstorage, this way I can take this data through all the aplication, but the hash is what makes my hooks update when I tried to wrote this strategy, and when the user updates the page I got the same behavior, because the hook could not find the :id on the url.
Final question
How can I persist the sidebar with the fetched data I did when I load the page?
NOTE
I did not post the code because at this moment I got too much code trying to solve this and I'm stuck in this problem for almost one month. I'll update this post later on.

Correct way to render Flatlist with external API in react Native

I have created a screen that has a flat list with a data source from an external API. I am storing those data in a state, using redux and then retrieving the data to flatlist.
I am for fetching the data from API I am using axios. So, to supply the source of data to flatlist, I am fetching the data in the previous screen. For example - I have a button, by which on pressing that button it will navigate to a new screen which contains a flatlist. So, I am fetching the data by posting axios request by the onPress function of the button from the previous page. And then storing that data to a state in the redux store, and then getting the data as a source to flat list.
I think this is not the right way to do this? How to fetch the data from external API on the same component and how to render that (because within fetching the data, the component will be rendered). How to do this effectively?
As, if everything is correct if the user goes to some other screen and re-enters the screen what will happen? How to do this effectively and optimized?
I think I don't have any code to show. If you guys need any code from above said, do let me know will update them.
You should probably try using componentDidMount for calling your api.
componentDidMount is invoked only once, immediately after the initial rendering occur.
You mentioned you are storing data in your redux store.
You should probably create events like:
const Actions = {
LOAD_POSTS_REQUEST: 'LOAD_POSTS_REQUEST',
LOAD_POSTS_FAILURE: 'LOAD_POSTS_FAILURE',
LOAD_POSTS_SUCCESS: 'LOAD_POSTS_SUCCESS',
};
const postReducer = {
posts: [],
isLoaded: false
};
Now, on LOAD_POSTS_SUCCESS you can set your data which you need in the flatlist with that also set a isLoaded state in the redux store.
Now next time, when user re-enters the screen you can use the state.isLoaded check to call the api.
I am sure that what I am mentioning here is a way simple implementation. Hope this helps.

Thinking in Redux

Im trying to understand redux while designing a sample App. Im confused with the concept of state vs data model.
Note: Im not using Reactjs.
Background of the Sample App.
2 tabular grids:
Grid A: List of members on my website.
Grid B: List of all orders by a member, selected in Grid A.
So the end-user of this app, can select only 1 member at a time from Grid A at a time.
The end user can also enter name of user in Grid A and my backend service will return the details for this member (for grid A) & all their past orders(Grid B).
Redux Questions
My backend service knows nothing about the order in which I list items in Grid A or B. Who should maintain order of items in the Grid? Is it responsibility of the store or the component?
Who maintains which member is clicked in Grid A? ? My backend service, returns me all the members and all their orders. It knowns nothing about the member that is selected on the UI.
Is it good practice, to have components keep this information and then augment the UI, whenever it refreshes from the data it gets from the store?
Redux is made to save your current app state. But how to show it is up to your components.
Actually it depends on an app. There are apps with a lot of similar tables and there are component libraries where sorting logic is handled inside the component. But if all your app is based on a few tables it makes sense to add to the store a property that indicates how your table should be sorted, something like: membersSortingType: [asc, desc, none]. And then you pass members and membersSortingType to a function which does the sorting and returns a new membersList which then can be passed to your component.
The same is here, when you click an item you can save it to the store like: currentMember: id, and to get data that should be rendered in your component you just pass your member id and all the orders to a function that will do some filtering. So any time you select a new member everything is automatically updated.

Possible to save data fetched by dispatching an action to a variable before it hits selectors/reducers?

I have data coming to the app from a Rails API and I have control over the shape of the JSON object that is sent. When a Redux action is dispatched, the data received is normalized on the front end before being sent to the store.
-simple enough-
What I am hoping to do is pass to the component that dispatches the acton a copy of the JSON data in its original, non-normalized form as props. This will save the 'de-normalization' process of taking that data from state and getting it into a form that is more useable for rendering in the component.
Any ideas on how/ where this can best be done?
Thanks!
FYI: This is a solution to an issue with relational data in normalized state that I have been trying to figure out.
A possible (straightforward) solution would be storing the 'de-normalization' version in a dedicated property in the store, your component or other part of your app could take it directly access it from there.
You can store this 'de-normalization' version directly in the reducer after the appropriate action was dispatched.

How to design standalone module in reduxjs?

Say we have a CountryPicker which on mount will send a request to server to load country list then display it, user can pick a country and it will dispatch a PICK_COUNTRY action and update UI correspondingly. Also it will display some helpful information when it fails to load country list. The logic of this component is rather complete and standalone.
Many of our pages use this CountryPicker and apparently we want to reuse the code.
Based on the situation, we have a CountryPicker React component, a CountryReducer and CountryActions.
The problem is, some of our pages using CountryPicker would like to do some thing more (like retrieve new data according to new country) when user picks a different country.
The solution I can think of is add a handleSelectCountry props for CountryPicker, and call it with new country payload when user picks a country.
This is kind of ugly to me, is there anyway to do it more unanimously? Thanks in advance.
You could use Store.subscribe to watch for changes in the state of the component and trigger actions from there.
http://rackt.org/redux/docs/api/Store.html#subscribe

Categories

Resources