When your last-child, first-child css condition doesn't work, we need to check html tags inside React code!
For example, my original code (like below) was causing such problem.
ํน์ ์ปดํฌ๋ํธ ๋ฆฌ์คํธ์ first-child, last-child ํน์ css ์กฐ๊ฑด์ด ๋จนํ์ง ์๋๋ค๋ฉด, ๋ฆฌ์กํธ ์ฝ๋์ html tag ๋ค์ ๊ฒํ ํด๋ณด๋ ๊ฒ ์ข๋ค. ์๋๋ ์์์ฝ๋์ด๋ค.
import styled from 'styled-components'
import React from 'react'
const Name = styled.div`
margin-bottom: 10px;
&: last-child {
margin-bottom: 0;
}
`
<ExampleTable>
<>
{/* item: { data: ['annie', 'bianca', 'cecilia'] } */}
{item.data.length && item.data.map((value, index) => {
return (
<>
<Name>
{value}
</Name>
</>
)
})}
</>
</ExampleTable>
<Name>
components to have bottom margin 10px
, but wanted to give 0 bottom margin
to <Name>
tag's last-child.<Name>
components. Fyi, <> </>
doesn't really do anything.<Name>
component list.[๋ฒ์ญ]
<Name>
์ปดํฌ๋ํธ ๋ฆฌ์คํธ์ ๋ง์ง๋ง ์ปดํฌ๋ํธ์๋ง ๋ง์ง์ ๋ค๋ฅด๊ฒ ์ฃผ๊ณ ์ถ์์ผ๋, ์์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ํด๋น ์ปดํฌ๋ํธ๋ค์ ํ๋๋ก ๋ฌถ์ด์ฃผ๋ html tag ๊ฐ ์๋ค. <> </>
์ด๋ ๊ฒ ๋น ํ๊ทธ๋ wrapper ์ญํ ์ ํด์ฃผ์ง ๋ชปํ๋ค.<ExampleTable>
<div> {/* change this!! */}
{item.data.length && item.data.map((value, index) => {
return (
<> {/* do not make this as a div */}
<Name>
{value}
</Name>
</>
)
})}
</div>
</ExampleTable>
<Name>
components.<> </>
as a div
tag inside return
. This will make html like this.
<div><Name /></div>
<div><Name /></div>
<Name>
component becomes both first-child & last-child inside the div
. This is not what you want.return
์์ ๋น ํ๊ทธ๋ฅผ div
๋ก ๋ฐ๊ฟ๋ฒ๋ฆฌ๋ฉด, ์์ ์์์ฒ๋ผ ๊ฐ <Name>
์ปดํฌ๋ํธ๊ฐ ํ๋์ ๋ฆฌ์คํธ ์์ ์์ง ์๊ฒ ๋๋ค. ๊ทธ๋ฌ๋ฉด first-child, last-child ๊ตฌ๋ถ์ ํ ์๊ฐ ์๋ค. ๋ชจ๋ ์์ด๋ค์ด first ์ด์ last ๊ฐ ๋๋ ๊ฒ์ด๋ค.On top of solution 1, you can add one more thing.
In the example code, it creates the list of components because we are using array of data. To make your code clean, you might want to create key
or index
for iterating items inside return
code.
Because you will see annoying warnings like this in a console.
But you don't want to make outer tag of <Name>
component as div
tag. We already talked above that it will mess up your css.
As alternatives, we have two possible solutions.
<> </>
.Just delete empty tag, and give key
to <Name>
component.
// ...
return (
<Name key={index}>
{value}
</Name>
)
// ...
A common pattern in React is for a component to return multiple elements.
Fragments let you group a list of children without adding extra nodes to the DOM.
- quote from official REACT Docs.
Here is example code of React.Fragment.
// ...
return (
<React.Fragment key={index}> {/* change this!! */}
<Name>
{value}
</Name>
</React.Fragment>
)
// ...
This way, you wouldn't mess up first-child or last-child css conditions AND have a key for each child component.
๋ฆฌ์คํธ ๋ฐ์ดํฐ์ด๊ธฐ์ ์ด๋ ์ด๋ฅผ ๋๊ฒ ๋๋ฉด ๊ฐ ๋ด๋ถ ์ปดํฌ๋ํธ์ key, index ๊ฐ์ ์ฃผ๋ผ๋ ์ฝ์ ์๋์ด ๋ฐ ๊ฒ์ด๋ค. ์ด ์๋์ ์์ ๋ ค๋ฉด 1๋ฒ์ฒ๋ผ ๋น ํ๊ทธ <></>
๋ฅผ ์์ ์ญ์ ํ๊ณ <Name>
์ปดํฌ๋ํธ์ ํค ๊ฐ์ ์ค ์ ์๋ค.
ํน์ ์ด๋ค ๋ค๋ฅธ ์กฐ๊ฑด๋๋ฌธ์ <Name>
์ ๊ฐ์ธ๋ ํ๊ทธ๊ฐ ํ์ํ๋ค๋ฉด, 2๋ฒ์ฒ๋ผ React.Fragment ๋ก ๋ง๋ค๋ฉด ๋๋ค. ์์์ ์ค๋ช
ํ๋ฏ์ด, ์ฌ๊ธฐ์ div
ํ๊ทธ๋ฅผ ์จ์ ์ถ๊ฐ์ ์ธ ๋
ธ๋๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ํผํด์ผ ํ๋ค.
Let's not forget to wrap same components inside a single div
tag to distinguish first-child and last-child of css. Hope this helped you solve a problem.
๊ฐ์ ์ปดํฌ๋ํธ ์ ๋ค๋ผ๋ฆฌ ํ div ์์ ์ ๋ฌถ์ฌ์๋์ง ํ์ธํ๋ ๊ฒ ์์ง ์๊ธฐ!
๏ฟผ