Im new in React and single apps and I have a question in this approach.
Im using React-router 4. When routing lets say I have a ToDos component (myapp.com/todos) that when visiting I fetch the ToDos data to something like "myapp.com/api/todos.json" and get the ToDos list and then render every ToDo, and if I want to go to something like ToDo component where you show the ToDo details would be a route like "todos/:todoid" then I use a and go to the ToDo detail and that works fine, but what happen when a user visit directly the "todos/1"?. Should I fetch the data from the server corresponding to that particular todo? something like "myapp.com/api/todos/1.json" ? or should I load the ToDo component and get all the todos ?
Is important because then I have to server rendering the routes and pass some props to the route like the open graph tags.
Any advice or tutorial or course would be appreciate. thanks in advance!
You don't need server side rendering, when the user opens 'todos/1' directly, then render ToDo-detail component and use onComponentDidMount to fetch('api/todos/1').
Related
I am making an e-commerce app with react and firebase the <cart /> component contains two child components
1-<BasketItem /> (this component will be duplicated as many Items as the user adds to the cart and it has the functionality to let user modify the quantity of the Item )
2- <OrderSummary /> (this component will show the user the the total price of his cart and the shipping fees)
of course all the data of the items and the total will be gotten from the database (I am using firestore) but but the issue is when the user update the quantity of the items from the <BasketItem /> component the total price from the <OrderSummary /> did not get updated as well because the database call will be done already and no way to recall the function that gets the data from the database because there is no parent- child relation between the two components and I can't pass props between them I have tried to use react-context-api for this but that did not solve the issue because the up to date is on the database and the only way to update the total value is to refresh the page and this is not a good user experience to have.
In any React all, all affected UI components should be updated when you update the cart information in the state (as they should all be observing that).
When using Firestore, you'll use a so-called CQRS pattern, where the updates sent to the database, are a separate stream from the listeners to the database. You'll typically add listeners when you create/mount the components, so that they're always listening while the component is visible to the user.
With that setup in place, the update flow becomes:
Your code write a new value to the database through the Firebase SDK.
This gets written to the database on the server at some point.
The servers sends this information to all other clients, and a confirmation to the client who wrote the value.
This triggers the listener that you registered before.
The listener updates the data in the state of the app.
And that then finally triggers a repaint of the affected components.
This is the general flow, but it applies to all cases I can think of.
Usually the best practice is to have the state stored on the front-end too in the form of context-api or redux-store or simply as component's state, they try syncing this state on the front-end with DB when user triggered submit/order action.
If you had to update your DB on every quantity change, then you have to update the same on front-end state/redux-store too.
I have a complex react component on my main page. I'm not using redux. On click of a button, I want to open the same instance of the react component with some new props in a new tab. The problem is I'm not sure how to keep them synchronized.
Let us say I have an array in the state of my component and I'm displaying the contents of the array in the component. Now based on the user's input, I will modify the array. I want the updated array to show up in the component which is opened in the new tab as well.
class App extends Component{
constructor(props){
this.state = {arr = []};
}
handleUserInput = arr => {
//make changes to arr
this.setState({ arr });
};
render(){
return(
// code to call this.handleUserInput()
<button href="/newtab" target="_blank"> </button>
{arr} //display the array here
.......
)
}
}
The scenario goes like this:
I will display this component on my main page and there the user can input something to the component based on which the arr in the state of the component will change.
When the user clicks on button, the same component should be opened in a new tab where url will be ending with "/newtab".
While both the tabs are open, and when the user inputs something to the component on the main page and triggers an update in arr, I want that updated arr to automatically reflect in the component present at "/newtab"
I'm using react routing like this:
const routing = (
<Router>
<Route exact path="/" component={App} /> //user inputs something on this instance of App and arr from this App instance will be updated
<Route exact path="/newtab" component={App additionalProps={additionalProps} /> // I want the updated arr from the App instance on the main page to show up here.
</Router>
)
ReactDOM.render(routing, document.getElementById('root'));
I clearly understand that, through this approach of using react-router to open a component in a new tab, I'm essentially opening a new instance of the App component in the new tab and it makes the App component on main page and App component on "/newtab" page completely unrelated.
I want to know if there is a way to share the state between these two components which are on different tabs. I'm half-way at implementing a local storage approach.
(or)
Is there is a way to make react-router open the same instance of the App component in a new tab so that there will be only one instance? If this is possible, will there be any problem wanting to pass new props to the component that opens at "/newtab"?
Will my problem be solved if I use redux?
Please let me know if I'm unclear anywhere and if I can provide you with more info. Thank you very much.
Your understanding of React is a bit skewed - you cannot open "the same instance" of a component, as components are not rendered to the DOM. Components are converted to HTML elements, so two different pages have two different DOM elements - they can't be shared.
What you're trying to do is share state between two tabs.
React does not support this, a new tab is a new app, it is a totally separate instance.
The only way to share state between two instances of an app that are open in the same browser would be to use third party / external APIs.
For example, you could connect your app to the browser's local storage. This means that both instances of the app would share the same local storage data. Be careful with this as you must not store any sensitive data (i.e. user details, passwords, bank details, access tokens) in local storage as it is susceptible to XSS and other attacks.
There is a guide here on how to do this (the author uses Redux) but I'm sure you don't NEED to use Redux to achieve this.
i am trying to code a simple dashboard with React, node and mongo.
Register and Login works well:)
So now i want to display the User Name on the Topbar with his Picture. I load the data (name and picture url) in the Topbar component via Ajax from the Server. So right, soo good.
Soo, but i need User Data for a lot of other components. (Friends, Notifications and soo soon) i can't in every componente an ajax call to my server make or? But i don't understand how to do this.
I need Data from the same Model in many different components.
You can use the context api or redux to create a 'global' store and access any data in it from anywhere down or up the component hierarchy without having to pass props down each level. In redux you can access any piece of this global state with the connect hoc.
More on redux
More on context api
Comparison of the two
I have an isomorphic react application using redux,react-router, react-router-redux, I want to bind my components with url query params and when the query params changed, send request to an API and update my state and finally fetch data.
I know with react-router-redux it automatically update my state.
Also I want to show a pre-loader (spinner) to user when data is fetching.
what is the best way to write an action creator for this issue ? thanks
I want to show a pre-loader (spinner) to user when data is fetching
Pass a data prop to your component. When it's undefined, show a spinner.
const MyComponent = (props) => {
if (!props.data) return <Spinner />
...
}
When the query params changed, send request to an API and update my state and finally fetch data
The most simple solution (this can get quite complex depending on your needs) is to fire this logic on the Component's lifecycle hooks.
When the route changes react-router, with a typical configuration, will cause the component to render if you were previously on a different route, and update if you were previously on the same route (i.e. the same path, but with different query params).
So for the first case, use componentDidMount, for the second case, use comonentDidUpdate(prevProps, prevState) lifecycle hook.
To map the asynchronous API call to redux action(s), use a library like redux-thunk or probably more tailored to this use case, redux-promise-middleware. How to use those is a bit deep in scope for me to go into here, but they both have excellent documentation.
In the end, you'll want to map those actions in a reducer put the response data somewhere in your state tree, then using react-redux bind that location in the state tree to the data prop on your Component, as I mentioned before.
My app uses react-router, redux, react-redux. Lets say I'm currently looking at /about route which renders the AboutPage component. Now I want to navigate to /news. Right now, when the route change happens the new component mounts, which fires off async actions to fetch the data. While that data is being fetched I am looking at the NewsPage component but with loading spinners.
What I'm trying to do is stay on the AboutPage component while all that data fetching is happening. I have successfully implemented the data fetching during react-router's onEnter hook. The problem is that, if AboutPage happens to use any of the same redux state as NewsPage, you'll see rendering changes while the data is being fetched and updated.
What I'd like is to somehow 'freeze' the current route while actions/state-changes are happening behind the scenes, and then render the new route component when thats ready (in the meantime users will see loading feedback via https://github.com/rstacruz/nprogress).
So either I need to completely unsubscribe the current route component from state changes or otherwise lock stuff in. Not sure if redux even exposes what I need but curious if others have solved this.