There is a tile (molecule) with an image, some text and a play button. When the button is triggered a video should be shown via a modal. I think a modal should be an organism, but i want the modal to be part of the tile, which is an molecule.
The modal should be part of the tile, because its easier to use it that way.
I dont want always wire them up from inside an other organism, template or view.
Should i make the modal to a moclecule or should i make the tile to an organism?
Any advice?
I know this is an old question, but I recently stumbled on this while trying to figure out basically the same thing and wanted to add my two cents.
Note: I just started learning about atomic design, so this could be completely wrong - Take it for what it is, an opinion.
Brief background
In my case, I have a component (lets call it Form A) which is going to live inside of Modal A. Modal A is a very simple modal which is more of just a dialog modal (basically just contains open/close functionality) but it happens to have a form inside of it in this case.
Since the Modal technically contains a form (molecule) visually, I initially figured this must be considered an organism, or at the very least, another molecule.
My Solution
After thinking on this for a while, and referring to https://atomicdesign.bradfrost.com/chapter-2/ for guidance, in my instance the following sentence made it clear for me. (in my opinion)
These atoms include basic HTML elements like form labels, inputs, buttons, and others that can’t be broken down any further without ceasing to be functional."
In my mind, going by this logic, I can break my modal down all the way to the atomic level...
If I remove the Form A component from the modal content, the modal is still functional (just has no content). To me, this tells me that I should in fact make a general Modal component and label it as an atom.
After I have a Modal atom component, I can simply pass it children to change the content of the modal. This allows me to easily have a Modal A, Modal B, Modal C component which in my opinion would then be an organism since at that point it is implementing the molecules to create a larger component.
Possible Answer?
So, if I were going to try to answer your question while using my own logic:
I would personally create a simple general re-usable modal component as an atom, then I would create an organism, say <PlayVideo /> which has inside of it the
<Modal props={modalSpecificProps}>
<Video />
{any other content to display in the modal}
</Modal>
With <Video /> being a child along with whatever else should be displayed inside the modal.
The only thing I would say I'm still unsure about myself is, can something be an atom, but still technically allow children to be placed in the atom as well?
Anyways, food for thought for anyone else that stumbles across this.
Related
I am trying to use a parent component to control animations in a child Canvas element. Specifically I want an animation to happen when a user inputs a correct answer.
It works until the user changes the state in the parent component, and then it no longer works.
I've made a stripped-back, minimal version of my code here to show my issue: https://codesandbox.io/s/epic-leaf-08jqvy?file=/src/App.js
My desired behaviour is that the red box bounces when a user clicks submit. That happens if they don't type anything in the input box, but as soon as you enter anything into there - changing state and re-rendering the component - the button no longer triggers the animation in the Canvas child component.
As far as I can tell, the issue is to do with changing the state when inputing text. If I make a version where the input is just assigned to a variable, it works fine, but I need to be able to use state and re-render other parts of it.
I have put a console.log in the jump() function, so I can see that it is being called, but no animation is taking place in the canvas.
I assume that what's happening is that everything is being re-rendered when the state changes, and so the useRef is no longer tracking to the right thing.
Things I've tried:
putting the canvas in a memoized component to prevent it from re-rendering
using eventlisteners to see if I can trigger the animations in other ways - keydown ones work, but I need the user to be able to type, so I tried other ones (like hashchange or audio.play) but neither of those worked.
You can see the thing I'm actually trying to build here: https://papaya-platypus-86565f.netlify.app/play Basically users answer questions and an animation plays depending on whether they're right or wrong, to give it a game-y feel.
Thanks!
I like your red box as well as your reasoning. Yes, the input state changing on keystroke is causing the entire App component to re-render. Note that your App.js component has a lot going on (all good stuff), such as your Box class instantiation, your canvas instantiation, etc.
The key is to break your components into smaller parts, particularly separating stateful components from non-stateful components. We don't want your canvas re-mounting on every input change, so we make them sibling components!
Here's a working example of your code, just in smaller components:
https://codesandbox.io/s/strange-julien-d3n4zm
I hope this helps.
I am struggling with atoms in atomic design. Why would I need to make a component for already estabilished HTML UI element? Isn't it redundant?
Lets say I have a button, in molecule instead of using the <button>Label</button> I would be force to use component <Button myOwnLabel="Label" /> inside which is just rendered the same old button.
I can't see the benefit of making another file. Can you help me see it?
Thank you.
There is nothing wrong with using <button> in React. I use it all the time for some small projects that do not require having complicated components for each element.
The benefit of atomic design orientation in React is to give you a consistent foundation for every element in your app.
For example, in your project, all buttons are blue, and every time someone clicks on them, an event is sent to Google Analytics. Using pure HTML elements, you will declare it as:
<button className="blue" onClick={sendEvent}>Text<button>
If you have 100 buttons, you will have to write this configuration 100 times.
Moreover, one day, you may decide that it is not useful to track clicks anymore, and you need to remove the default onClick event on 100 of them.
Then your designer says, let's change all buttons to orange, and you repeat the whole process again.
That's when using custom element comes in play. You can declare the above code in a separate <Button> component.
const Button = () => <button className="blue" onClick={sendEvent}>Text<button>
It appears as simple as <Button> everywhere else, but the actual content of the <Button> is dynamic. Any update will require you change the code inside the component only. For the above example, to achieve all the change requirements, you only need to change <Button> to
const Button = () => <button className="orange">Text<button>
and it will be reflected in all of its instances.
Hope this helps.
This Is more of a "theoretical" question that often buffles me in different situations and use cases, I will give a simple example to demonstrate it.
Let's say I have a list of 10 buttons.
Everrytime I click a button, a floating menu appears on top of the clicked button - there is only one menu visible for any given time.
Let's assume that I can't render this floating menu within the button component and I can only render it in the buttons parent level (meaning that this menu is sibling to those buttons).
I have 2 possible options to do that:
Keep the x,y position of the last clicked button and render the menu in this given position
Render the menu once and using "ref" to directly relocate the menu
On the one hand, the first approach seems more "Reactish". On the other hand, the possible implemention I can think of is pretty ugly (capturing the clicked item position and saving it to state which triggers defender), and further more, I am not so sure about re re rendering the whole container just because I need to move a small piece of it.
The second approach touches the DOM directly using refs. Although possible , doing DOM manipulations sometimes feel bad to me.
Is there a better approach? Which of the 2 makes more sense?
Any suggestion or thoughts will be appreciated!
Thanks
React uses whats called a virtual DOM, which is a representation of the DOM, that sits on top of the real browser DOM. Whenever you update state or a user performs an action the virtual DOM compares and checks the changes with the real DOM and then updates the UI accordingly.
So if certain DOM elements like a are not different between changes it does not get re rendered, only the DOM elements that have changed are re rendered. And if a property on a DOM element is changed, only the property is updated and the DOM element is not re rendered.
<div color="blue" />
to
<div color="red" />
The whole element is not destroyed and re created, only the property is changed.
However if the element in the host tree is different than the entire host tree is destroyed and recreated.
<div />
to
<p>
This is refereed to as reconciliation
https://reactjs.org/docs/reconciliation.html
So using refs is definitely more of a hacky solution since its more of an escape hatch and directly manipulates the DOM.
I would definitely stick with option 1, I think there is an elegant solution to the use case you described, it would involve just adding a click event listener in the componentDidMount and keeping track of the click position that way.
And also its hard to say without code but since your buttons will be the same, they will not be re rendered only the menu will.
Would recommend for further reading
https://overreacted.io/react-as-a-ui-runtime/
I've posted this on Reactiflux but may get more traction here. I've created a sandbox to demonstrate my need: https://codesandbox.io/s/xvnk0znw7z
What I'm trying to do is create a generic modal wrapper that I can use to encapsulate several components; in the sandbox, the component is a date range picker, but I also have a formik component for example.
The thing is, the Apply and Clear buttons need to be a part of the wrapping modal, and not the child component it wraps.
However, when clicking on Apply or Clear, saving the child component state to the Context (not included for brevity) is really the responsibility of the child component itself; only it knows how it should do it.
In the example above, that would be the ok and clear methods of DatesPicker. Intuitively, I would call children.ok and children.clear from the wrapping modal, but I know for a fact that's not how it should be done.
I looked a lot at the Cat and Mouse render-prop example in React's docs, but I can't get my head around how I can apply this here.
I am looking for a good code pattern to allow some communication between components, when using React & Redux.
Most likely this communication should be done via redux, like many articles suggest. (like this one, for example).
However, there are some situations when using the store would be a bit of a hack rather then using it for state management. These special cases are usually when you need to give a command to a component, like show or hide.
I will give an example:
Lets say that we have a <Tooltip /> component which all it does is render some help icon, that when clicked, opens a tooltip popup.
And lets say that we have more than one in a page, but we want to make sure that only one is open at a given time. So if tooltip A is open, and the user clicks on tooltip B, then B should open and A should close.
Here are some patterns that I thought might be relevant to implement this requirement:
Using Redux: We could have in the store some state for these tooltips:
{
showTooltip: "A" // the ID of the tooltip to show
}
This means that we have to connect the tooltips to the redux store, and check for each tooltip if it's ID is the one that should be opened, and when the user clicks on the tooltip icon, we dispatch an action to set the opened tooltip.
Using additional event mechanism: We can use an additional event mechanism to Redux, like emitter.
In this case we can fire an event whenever a tooltip is about to be opened, and all other tooltips can listen and hide themselves once they get such an event.
I have to say that it seems to me that maybe having two event mechanisms in the app seems a bit redundant, but on the other hand, using redux store to communicate with components seems a bit overkill.
Would love to hear some opinions about this issue.
The React and Redux world generally encourages representing your app's behavior as state. For example, rather than an imperative $("#someModal").show() command, you might save a flag value somewhere that says {modalVisible : true}.
There's numerous examples of using state to drive modals and popups. A typical implementation would store the values for a single modal or a list of modals in state somewhere (either in a parent component or in Redux), and then render modal components as appropriate based on those values, such as: {type : "notificationPopup", level : "warning", message : "Something happened!"}. The basic approach works whether you're storing the data in React, Redux, MobX, or something else.
For specific examples, see Dan Abramov's answer to "How can I display a modal dialog in Redux?", Dave Ceddia's article "Modal Dialogs in React", the article "Scalable Modals with React and Redux". I also have other articles that demonstrate modal management in the React Component Patterns#Modal Dialogs and Redux Techniques#UI and Widget Implementations sections of my React/Redux links list.