I was trying to toggle the page with a buttonLink and list elements when I click on the buttonLink. I can basically see 2 popular possible approaches to this:
Using react router and create routes one for the list button and another for the list elements that opens up when clicking on on list button element which gets list elements as props in router
Pass the props to list element but render it in the same page, but with state toggle condition. Example -
this.state.showList===true ? :
Here I'm confused to decide between these 2 approaches. I preferably chose the 2nd approach to toggle between components based on state as I'm less comfortable with Router. But if the number of components in that page increases, it is difficult to maintain it using state value.
But I would like to know that standard approach for medium scale applications.
Any examples or pointers would be helpful, thanks.
I'm using both approaches and distinguish between encapsulated business logic and modifying logic. For example you have persons and relations between those persons. So I have 2 routes <personId>/details and <personId>/relations. With the first you will see person details like name, address, telephone numbers and with the second you see a network of related persons, who are connected with this person. For me I decide between those 2 approaches by what I expect to see after reloading the page (pressing F5). When I'm on the detail page I want to see the details again and also I want to see the relation network again.
But there are some modifying logics like adding a new a new telephone number. Normally you would do this by showing a modal dialog or expanding a form with some inputs and "OK"/"Cancel". When this dialog is opened and doing a page reload I would expect to see the person details again. So I'm implementing this dialog via {this.state.showAddTelephone && ...}
In my opinion just go with react-router. Routes are used in multiple areas of the app. The logic of conditional rendering can introduce too much complexity if it's being used in a lot of places. It would be easier to just take the declarative approach of the router with no logic behind it.
Related
I am developing a website in React.
In this website I have a screen - lets call it "book-an-appointment"
And I have multiple flows:
book an appointment for existing client
book an appointment for non-existing client
book-an-appointment is part of flow 1 and 2, with slight differences:
some buttons that are shown only in one of them
"next" button that takes the user to a different screen
it affects differently on the funnels
of course each one of them is in a different URL
and more...
Question: Which approach is best practice in developing such screen in react?
options I thought about are:
Creating A single screen that shows the relevant buttons and actions according to the state
Duplicating the screen for each flow (because of the small differences in it)
I am quite new to react. tried to look for an answer here and in google but couldnt find my answer.
In that case I would just use one Parent component with ether two child components with the different flows. You can make one JSON object where conditionally you add specific keys and you can later check if the isExisting field exists for example what kind of booking it is and show a the existing user flow component.
You could do it like that or have one component that just conditionally hides fields depending on what type of booking it is. In this case you would use conditional rendering. See the article below for more info.
https://reactjs.org/docs/conditional-rendering.html#inline-if-with-logical--operator
Let's say component - TodoList need to show the list of TODO's in 2 different ways, listview and gridview .there is a switch on the page that toggles between the views. Assuming I want to keep the 2 views as different components, what is the best practice -
create TodoList component with graphql query and then pass the result of the query to TODOListView and TODOGridView components?
create TodoList component with NO graphql query and then write the same grqphql query inTODOListView and TODOGridView components (not DRY, query duplication in each component, but apollo cache will make sure that it is not called multiple times)?
good/bad with each approach?
IMHO there is no real choice, cache usage has no value as argument then no good parts with second approach.
Taking usability, UX, user centric design you probably want to keep page, sorting and filtering state while switching type of view. As an user you're expecting this kind of behaviour. This is easily available only with first solution.
Assuming I want to keep the 2 views as different components
IMHO this is wrong assumption, too. Of course you can do that but Lists are almost the same, the real difference is in item/row rendering. If this is a simple styling sets change (or adding a few elements) then even no need for using components for items, just conditional rendering. You can change/refactor it later.
Utilizing item components you can have additional abstraction layer and more complex use cases available. With passed down (into items) switching type handler I was able to change it (gloablly) from simgle item level or change locally item view type - mixed element list.
I'm asking this to make sure I understand the concept. In UI Router, they recommend you use nested states as much as possible. However, it seems when you do that, you can only have 1 controller per state/view. Which in most cases is fine. However if you need two or more controllers on a state/view then it seems that Multiple Named Views is the right solution. Because it seems that you can actually have different html elements or divs controlled by different controllers - if necessary.
So for example on a search results page, you could have different elements or divs on the page controlled by different controllers.... is this what Multiple Named Views in UI Router is designed for?
It seems for more complex pages, like a search results page, Multiple Named Views is a better solution than simply having nested states... because you could have an Authentication controller, autocomplete controller, search controller - all being responsible for different areas on the page. I'm not even sure how you accomplish something like that with nested states.
So am I understanding this correctly?
I think you are confused with the fundamental definition of views and states. That being said, your understanding (to your own problem statement) is correct.
In ui-router, the fundamental principle it is making your app into a state machine. The basic definition of state machine is that, at any point of time, only one state can remain active. This is actually quite useful and a good design pattern - in a sense that you can define what your machine (or app) should do (or how it should behave) when it is in a clear defined state. Good for debugging too.
However, it doesn't mean that in a single state, the machine cannot do multiple things. It can, as long as in that state, its job is to do multiple things. Let's take a movie booking app as an example.
Disclaimer: this is not exactly a real state diagram but lets just use it for discussion purposes. Image courtesy of Google Search
Now all the blue rounded rectangular boxes are states. Meaning, when the user uses the app, at any point of time, he/she will be in one of the states - he must, or else he is not using the app.
Now it can be quickly realized that if the user is in SeatsChoosing state, he CAN'T be in other states - not PromotionSelection, not Payment, or other states, at the same time. He can go to other states (called state transition), say PromotionSelection, but only after he has done choosing. The point is that no more than one state is active here aka no Parallel States. Only one at a time.
While it only can be one state active at a time, but that doesn't mean machine cannot perform multiple tasks at a single state. Take the SeatsChoosing state as an example. In the SeatsChoosing state, multiple tasks are performed, including loading the movie, fetching the location, display the schedule, etc. But the user will experience all these things, only if he is in SeatsChoosing state. The point is you can have multiple tasks executed at the same time in a single state, as long as your state definition allows it.
And that's is exactly what ui-router is achieving. At any point of time at your app, you can only have one state active. The nested states are still a single state by itself, its just actually a node traversed down the state machine - and when you are down to that node, only that node is active. No parallel states are allowed. For the same token, it doesn't mean your state cannot do multiple things at one time. That's where named views are for. For a state, you can have different views that has different clear defined contexts (view), which all of them fall under the same domain (state) as a big umbrella.
Now lets go back to your Search Results problem statement. How do you define your state, and how do you define your views? This is entirely up to you, but just make sure if you are using ui-router, you adhere to the state machine's rules - aka no parallel states but allows parallel tasks. So if you define a state is a page that does multiple things - authentication, autocomplete, etc, then yes multiple named views is the correct way and not nested states. But if you are separating search and search results as two different domains, then, maybe nested states will be better.
There is no right and wrong answer for this, just a matter of design decision.
Hope that helps.
I'm going to create a large scale application with react and redux and start to build the header component of the layout very first time. The layout header will have 4 child parts.
1. Icon that will show all the online users after clicking on it
2. Icon that will show latest 10 notifications after clicking on it
3. Icon that will show latest 10 messages received after clicking on it
4. Logged in user name that will be dropdown button to show some "My profile, logout, account setting" navigation links.
As I've read about redux at so many places that we must have as less as possible stateful components. So by keeping this concept in mind, I thought to have only one header smart container with a header state consisting default states for all icons like
{headerOnlineUsers:[], headerMessages:[], headerNotifications:[]}.
So if I follow the redux best practice and create only one smart header container with 4 different dumb components, the each and every time the state of any of them is changed, the whole header container will get re-rendered.
But I want to re-render only the state changed component.
For example, If I get a user joining the chat through websocket, It will dispatch an action and the reducer will update the headerOnlineUsers list of the state. But In this case I want my only online users component to be re-render not the whole header container.
Can anybody please suggest me the best approach to implement this kind of layout.
I would not go for your option, but would prefer a more granular approach.
What if you split the header in 2 later on, or want to display the button somewhere else ?
What if you have another version of your header for a subsection of the website ? You would need another container that gather again all the info.
The logic in general in redux is to separate what is data-sensitive and what is not. Your individual lists are data sensitive, the header in itself has no reason to be so far. What's more, if you want to attach actions to the icons it will quickly become messy to bring back thoses actions to the header and then its container, and even messier if you ever need to move them.
The way I would do it (and the way I do it right now as I halso develop quite huge app with react and redux), would be to have a store with those 3 lists of items, and then 3 containers, one for each icon/dropdown that links one aprticular list to the component.
Then the header is just a stateless function holding all the containers together. This way if you ever need to move one button somewhere else or reuse it, you just import the container and voila!
React.js will take care of only re-rendering what is required. So this problem is already solved for you :-)
What you plan to do sounds sane to me, I just would change one bit: The smart header container should not use internal state. Instead, your redux store should look like this:
{headerOnlineUsers:[], headerMessages:[], headerNotifications:[]}
and you should pass the redux store into the smart header container (have a look at the connect function in the redux documentation). This way, you can use the redux store contents in your component via this.props, and that's it.
I'm debating refactoring parts of a site I'm working on from jQuery into react. Before I start I'd appreciate some feedback on my thought process so far.
<DeviceChooser>
<ManufacturerSelect />
<DeviceSelect />
<ButtonOne />
<ButtonTwo />
<DeviceChooser>
That is the desired component. It's behavior is:
The parent (DeviceChooser) gets some json data via ajax on componentWillMount.
It passes part of that data to ManufacturerSelect, which is a select field.
Once something is selected there, DeviceChooser passes some other data to DeviceSelect, which is also a select field.
Once something is selected there, if some conditions are met, both Button1 and Button2 become active
Clicking Button1 or Button2 would redirect the page to a specified url, with parameters set depending on the 2 select fields.
More practically speaking, you choose your phone manufacturer, then in the next select you choose your device from that manufacturer, then you get redirected to either page1 or page2 with some get parameters depending on the button you press.
My questions are:
Who's responsibility should it be to decide whether the buttons should be active? The DeviceChooser or the Buttons?
Who should compose the redirect URL? The Chooser or the Buttons?
I'm going to have variations of this DeviceChooser component all over the website, what can I do to ensure at least some reusability? The caveat being that sometimes it will have more select fields that just 2, and other times different select fields will be part of the equation depending on state (Like, if your device is a laptop, you also specify what shape of edges the device has)
I'm really grateful to any feedback at all. I've also created a Gist with the code I've come up with so far, if it helps.
One of the methodologies that I have followed since getting invested in React is using containers. Containers essentially are components that are responsible for retrieving and manipulating the data and then passing all the relevant data down to all the child "dumb" components that are simply responsible for rendering said data.
Operating under this premise (or something similar) I would suggest doing calculations in the container on the initial data, and pass everything down.
So in this instance we should be do the following in the container (or parent component)
Get JSON data via componentWillMount
Manipulate the data and pass it to ManufacturerSelect
The other questions depend on which framework you're using. Are you able to elaborate on this? Are you using Redux, Flux, ReFlux etc?
I've had a quick look at your code, one super useful thing that I think you should do is specify PropTypes for each component. This helps immensely for debugging, and when you're talking about reusing components in several distinct locations this will be crucial. Also (without understanding the full context) is it necessary to use state everywhere in your components? Would it be possible for them to simply render the props passed down to them? (again this depends a little on the store you'
re using).
It's a relatively generic question, but my line of thinking (quite opinionated) would be as follows:
Your Buttons should become simple, generic Button components that should for this example have the following props (besides perhaps some styling props):
disabled
title
onClick
Your Device Chooser is the one who's got the awareness that components mix together, that these buttons should actually continue to do something after they're clicked, so you'll want to handle that knowledge solely within that component. It glues the rest together (passes data around) and should therefore also make these decisions.
<DeviceChooser>
<ManufacturerSelect data={this.state.manufacturers} />
<DeviceSelect data={this.state.devices} />
<Button
disabled={this.state.selectedManufacturer === null ? true : false}
title='Manufactuer details'
onClick={this.handleManufacturerDetailsClick.bind(this, this.state.selectedManufactuer}}
/>
<Button
disabled={this.state.selectedDevice === null ? true : false}
title='See device details'
onClick={this.handleDeviceDetailClick.bind(this, this.state.selectedDevice }}
/>
<DeviceChooser>
Device chooser's method than can be something like:
handleDeviceDetailClick(device) {
history.pushState('/device/detail/' + device.id);
}
You want to separate your functional components from the stateless ones. A good read for this is http://tylermcginnis.com/functional-components-vs-stateless-functional-components-vs-stateless-components/