After using react (actually the ClojureScript wrapper reagent) for a while now, I'm still not sure what's the best way to solve the following problem:
Say you'd have a Root component:
class Root extends React.Component {
render() {
return (
<div style="display: flex">
<div style="flex: 2 1">
<Content></Content>
</div>
<div style="flex: 1 1">
<Menu></Menu>
</div>
</div>
);
}
}
This separates the screen vertically into a bigger content section and a smaller menu section. I'd say this separation is clearly something the Root component should take care of. The Menu component itself might be used in another context in which the flex props don't make any sense.
class Menu extends React.Component {
render() {
return (
<div style="background-color: red">
Buttons, etc...
</div>
);
}
The menu however has some properties which belong definitely there: like for instance the background color. But if we run this example we'll notice that the background color does not fill the 'menu' area defined in the Root components. That's because its lacking a some height/width = "100%" style properties.
I see two ways to solve that: Either put them inside the Menu component. But this might as well not be intended in other uses of the component. If someone wants to use Menu not in it's full height it would have to be wrapped again.
Or, pass the width and height as props to the component, that's also quite some overhead...
Usually menu's are not reused that much, but this pattern arises in many other situations. What's the way to go here? Is there maybe a third way to do this?
EDIT/NOTE:
Maybe transferPropsTo is what I need, but I'd still leave this to discussion...
Is the align-items flexbox CSS prop of any use here?
https://css-tricks.com/snippets/css/a-guide-to-flexbox/#article-header-id-7
Related
I have two components like this.
<ComponentA />
<ComponentB />
Where component A will be horizontally scrollable but i want to show its scrollbar in component B.
<ComponentA >
some content over here which is wide enough to get horizontal scroll
</ComponentA>
<ComponentB>
some content
//scrollbar of ComponentA
more content
</ComponentB>
Hope i made the problem clear :)
I guess i can use useRef but don't know how in this scenario
I am newbie i hope i understand your question and i try my best.
use overflow-x/overflow-y: scroll;
so you can easily get a scrollbar in component A, but this will always visible.
Hi, I am currently a beginner to React.js, and I want to know if I could divide the a page's body with different background color without adding multiple components.
I have implemented the header and the footer, but I do not have any ideas to divide a body area into three parts. For example,
function App() {
return (
<div className="App">
<Navbar />
<AreaOne/>
<AreaTwo/>
<AreaThree/>
<Footer />
</div>
);
}
I was thinking about to use this kind of method, but I think it might be a better / more commonly used method. Any ideas would be appreciated
I'm relatively new to Vue JS and it is my first frontend framework. I used Vue 3 without deep prior knowledge of CSS & HTML.
I have coded a few components for my job but one thing I realised is that I tend to put width & height as the props almost all the time. (Then maybe use a computed property for the child component's style)
Example below:
<template>
<child-component :style="childStyle" class="child">
...
</child-component>
<svg>
<rect :width=`${getChildWidth(width)}` :height=`${getChildHeight(height)}` viewBox=`0 0 ${getChildWidth(width)} ${getChildHeight(height)}`/>
<svg/>
</template>
<script setup lang="ts">
import {computed, toRefs} from 'vue';
const props = defineProps({
width: {
type: Number as PropType<number>,
required: true,
},
height: {
type: Number as PropType<number>,
required: true,
},
})
const { width, height } = toRefs(props)
function getChildWidth(width: number) { ... }
function getChildHeight(height: number) { ... }
const childStyle = computed<StyleValue>(() => ({
width : `${getChildWidth(width)}px`,
height : `${getChildHeight(height)}px`,
}))
</script>
<style scoped>
.child {
...
}
</style>
My question is whether there are any best practices associated with managing Vue component sizes more dynamically and also what's the best way (with a simple example) to use CSS to dynamically control child-component's size. I'm afraid that using Javascript to dynamically control component sizes all the time may reduce code reusability and/or introduce a lot of code. Pls enlighten me. Thank you.
Edit 1 : Add SVG into the question
Thank you user entio for your answer. Sorry I forgot to add SVG because that's when I think that I'm forced to explicitly use pixel sizes propped down from the parent. How should I do the same with components containing SVG elements?
Always try to build your layouts and size your components using CSS. There're new, useful features of CSS allowing you to create layouts much more efficient than it used to be, to name one: CSS grid. There's a nice game tutorial helping to grasp the idea: https://cssgridgarden.com.
Another feature may be the Flexbox (another game - tutorial: https://flexboxfroggy.com).
When it comes to choosing which component should bear the responsibility of sizing - it really depends on the role of the component. Some of them are layout components (f.e. component having a main part and a sidebar) and these probably define sizes for the children components. Others are just atoms, and they use their own sizes (as you don't want to externally constrain a size of a button or tag for example).
I think that it could be beneficial to you when thinking about components (at least I found it useful) to read Brad Frost's Atomic Design. It's a set of principles he lays out to highlight various roles a component may take in a design system (or an application). You most probably won't need a book, there's plenty of resources available online.
Most of the times I tend to create my components so that they are responsive (adjust their dimensions to it's parent). If I want to constrain the component size I most of the times do it in the parent component. It then enables me to use the child component in a various places, independent on the space available in these places.
I have a React Native Expo app in which I'd like to make an element full-screen with essentially the following styles:
{
bottom: 0,
left: 0,
position: 'absolute',
right: 0,
top: 0
}
The problem is, I want to do this for an element that is deeply nested within the structure of my screen. As a simplified example, the structure of my current screen is something like the following:
<View>
<View>
<View>
<ComponentA>
<ComponentB>
<ComponentC>
</ComponentC>
<ComponentC>
</ComponentC>
<ComponentC>
</ComponentC>
</ComponentB>
</ComponentA>
</View>
</View>
</View>
What I want to do is set up something in ComponentC so that when you tap a button in that component, it causes an element within that same component to display full-screen.
Apparently though, in React Native, all elements are position: relative by default. As such, when I apply the styles above to the element I want to be full-screen in ComponentC, it doesn't show up as full-screen, but rather as filling the entirety of that particular ComponentC only.
Is there any way to get around this? I was thinking about taking the part of ComponentC that I want to have full-screen and placing it outside of ComponentC and at the top of my screen structure, but then, it's completely separated from ComponentC itself, and then I'd have to also coordinate that separate element so that it works with all of the various ComponentCs on the screen. Also, when I tried doing that, I ran into a bunch of issues with trying to properly maintain state.
Maybe I'm just taking the wrong approach to begin with, but is there a way to get what I want with some simple styling so that a deeply nested element can still be displayed full-screen, or am I going to have to engineer some complex thing to do what I want, and if it's the latter, any recommendations on how to approach this? Thank you.
To show something full screen no matter where you are in the hierarchy, you can use the Modal component: https://reactnative.dev/docs/modal.
Note: this solution will not work out-of-the-box if you want the relatively positioned element to fluidly transition into full screen (so-called hero or shared-element transition) - not sure if that is what you are after.
If you want to split your component, you can communicate from ComponentC to the top component directly with DeviceEventEmitter
in ComponentC:
import {
DeviceEventEmitter
} from 'react-native'
In the function which handle the onPress action of your button you can call DeviceEventEmitter like that:
DeviceEventEmitter.emit('whateverName', { myData: {} })
Then in the top component
DeviceEventEmitter.addListener('whateverName', (myData) => );
Ok - So I am kind of struggling with this. I am trying to achieve something pretty straight forward I think. I need 3 resizable divs within a fixed width container div without using Jquery. The resize needs to occur for all divs only horizontally as they all have the parent divs height. Here is the layout
<div id="container">
<div id="m1">M1</div>
<div id="m2">M2</div>
<div id="m3">M3</div>
</div>
My object here is to wrap this into a ReactJS component and therefore not wanting to muddy the waters with Jquery. Any help/direction would be most appreciated. If someone can mock up something like this in React, that would be awesome too! :)
Not sure whether this can be a CSS only solution but I am open to ideas
Thanks
Your question isn't exactly clear to me, if your container div is fixed width (as in a constant value) then your child divs should not resize dynamically no matter what the width of anything beyond the container is.
The only other way I could interpret your question, is that you need some sort of grid system, where you can drag to resize the width of the child divs within the confines of the container. In that case, I might be wrong but I don't think the solution is that simple, you might want to take a look at this package: https://github.com/STRML/react-grid-layout
More specifically, their simplest implementation allows you to define a fixed width container (1200 in this case) like so:
<ReactGridLayout className="layout" layout={layout} cols={12} rowHeight={30} width={1200}>
<div key={'a'}>a</div>
<div key={'b'}>b</div>
<div key={'c'}>c</div>
</ReactGridLayout>
If you want to fix the parent div's size and then have the inner divs automatically resize based on the parent div you can use the flex box layout which you can find here: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
In your case you can set the styling of the first div to:
.container {
display: flex;
}
And for the children (in your case identified by m1, m2, and m3) you need to set the css property flex-grow to how big do you want it to be relative to the others. Say, if you want m1 and m2 to have the same size and m3 to be twice as big, you would do the following:
#m1, #m2 {
flex-grow: 1;
}
#m3 {
flex-grow: 2;
}
Depending on what you want to do, you might want to consider renaming the ids/classes.
In case you are looking to get the exact size of the parent of a div you can do this as following:
render() {
return <div ref="node"></div>
}
componentDidMount() {
const parentWidth = this.refs['node'].parentNode.clientWidth;
// Do whatever you need here (like setting state of the react component)
}