In React, how to setState a Data by using hook useState? - reactjs

I am just getting started learning React Functional component and styled- component. I tried to setState detailePageData
const const [marketPriceData, setMarketPriceData] = useState([]);
and I tried to set up the marketPriceData by using JSON file.
useEffect(() => {
fetch(`/data/detailPageData.json`)
.then(res => res.json())
.then(data => setMarketPriceData(data.result.order_history));
}, []);
When I console.log marketPriceData. I got this
In here, I only need the price in each array. So, when I console.log(marketPriceData[0].price); I got 378000 what I expected.
Here is my main question, I only need each array price such as; 378000,341000,388000, etc.
I think I have to edit this part
useEffect(() => {
fetch(`/data/detailPageData.json`)
.then(res => res.json())
.then(data => setMarketPriceData(data.result.order_history));
}, []);
First, I think "Can I use foreach method? or for loop..?" I am not sure how to setup the logic to store the setMarketPriceData. Could you please help me with how to get the price what I expected?
Just in case, I will leave the whole code,
import React, { useState, useEffect } from 'react';
import styled from 'styled-components';
import { FaRegArrowAltCircleDown } from 'react-icons/fa';
import { Line } from 'react-chartjs-2';
import { Modal } from './components/Modal';
import TransitionHistoryModalStyling from '../ProductDetail/components/TransitionHistoryModalStyling';
import DropDownMenu from '../ProductDetail/components/DropDownMenu';
const options = {
scales: {
y: {
beginAtZero: true,
},
},
};
export default function MarketPrice() {
const [showModal, setShowModal] = useState(false);
const [marketPriceData, setMarketPriceData] = useState([]);
// https://github.com/reactchartjs/react-chartjs-2/blob/master/example/src/charts/Line.js
const data = {
labels: ['1', '2', '3', '4', '5', '6'],
datasets: [
{
label: 'MarketPrice',
data: marketPriceData,
fill: false,
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgba(255, 99, 132, 0.2)',
},
],
};
// useEffect(() => {
// let i = 1;
// if (i < detailPageData.order_history.length) {
// setMarketPriceData(detailPageData.order_history[i].price);
// }
// },[]);
const [detailPageData, setDetailPageData] = useState([]);
useEffect(() => {
fetch(`/data/detailPageData.json`)
.then(res => res.json())
.then(data => setDetailPageData(data.result));
}, []);
useEffect(() => {
fetch(`/data/detailPageData.json`)
.then(res => res.json())
.then(data => setMarketPriceData(data.result.order_history));
}, []);
console.log(marketPriceData);
console.log(marketPriceData[0].price);
// console.log(detailPageData.market_price[0].sizes[0].size);
// console.log(detailPageData.order_history);
// console.log(detailPageData.order_history.length);
// console.log(detailPageData.order_history[0].price);
// console.log(detailPageData.order_history.price);
const [currentMenuIndex, setCurrentMenuIndex] = useState(1);
const handleSelectedMenu = tabIndex => {
setCurrentMenuIndex(tabIndex);
};
const openModal = () => {
setShowModal(prev => !prev);
};
return (
<MarketPriceWrapper>
<TitleWrapper>
<MarketPriceTitle>시세</MarketPriceTitle>
<ShowAllSizes>
{/* <AllSize>230</AllSize>
<FaRegArrowAltCircleDown /> */}
<DropDownMenu className={DropDownMenu} />
</ShowAllSizes>
</TitleWrapper>
<SalesGraphWrapper>
<Line data={data} options={options} />
</SalesGraphWrapper>
<ButtonsWrapper>
<Button
isActive={currentMenuIndex === 1}
onClick={() => handleSelectedMenu(1)}
>
체결 거래
</Button>
<Button
isActive={currentMenuIndex === 2}
onClick={() => handleSelectedMenu(2)}
>
판매 입찰
</Button>
<Button
isActive={currentMenuIndex === 3}
onClick={() => handleSelectedMenu(3)}
>
구매 입찰
</Button>
</ButtonsWrapper>
<TableWrapper>
<TableColumnSetting>
<SizeName>사이즈</SizeName>
<PriceName>거래가</PriceName>
<DateName>거래일</DateName>
</TableColumnSetting>
<RowSection>
{/* {detailPageData.market_price &&
detailPageData.market_price.map(price => {
return console.log(price.sizes[0]);
<Size key={price.id}>
<Size>{price.sizes[price.id].size}</Size>
<Price>{price.sizes[price.id].avg_price}</Price>
<Date>{price.date}</Date>
</Size>
})} */}
<Size />
<Price>24,000원</Price>
<Date>99/11/17</Date>
</RowSection>
<RowSection>
<Size />
<Price>24,000원</Price>
<Date>99/11/17</Date>
</RowSection>
<RowSection>
<Size />
<Price>24,000원</Price>
<Date>99/11/17</Date>
</RowSection>
<RowSection>
<Size />
<Price>24,000원</Price>
<Date>99/11/17</Date>
</RowSection>
<RowSection>
<Size />
<Price>24,000원</Price>
<Date>99/11/17</Date>
</RowSection>
<OrderHistoryButton onClick={openModal}>
체결 내역 더보기
</OrderHistoryButton>
<Modal showModal={showModal} setShowModal={setShowModal}>
<TransitionHistoryModalStyling
detailPageDataMarket={detailPageData}
/>
</Modal>
</TableWrapper>
</MarketPriceWrapper>
);
}
const MarketPriceWrapper = styled.div`
width: 550px;
margin-top: 40px;
padding-left: 40px;
`;
const TitleWrapper = styled.div`
display: flex;
padding-top: 19px;
padding-bottom: 12px;
border-bottom: 1px solid #ebebeb;
`;
const SalesGraphWrapper = styled.div``;
const MarketPriceTitle = styled.span`
padding-top: 4px;
display: inline-block;
line-height: 16px;
font-weight: bold;
color: #222;
`;
const ShowAllSizes = styled.div`
margin-left: 370px;
`;
const AllSize = styled.span`
display: inline-block;
margin-right: 5px;
margin-left: 350px;
font-size: 18px;
`;
const ButtonsWrapper = styled.div`
display: flex;
justify-content: space-evenly;
margin-top: 40px;
border-radius: 10px;
background-color: #f4f4f4;
`;
const Button = styled.button`
display: block;
margin: 2px;
line-height: 16px;
padding: 7px 0 9px;
width: 400px;
font-size: 13px;
text-align: center;
border-radius: 8px;
border: none;
background-color: ${props => (props.isActive ? '#ffff' : '#f4f4f4')};
color: rgba(34, 34, 34, 0.8);
`;
const TableWrapper = styled.div`
margin-top: 40px;
`;
const TableColumnSetting = styled.div`
border-bottom: 1px solid #ebebeb;
padding-bottom: 9px;
text-align: right;
`;
const SizeName = styled.span`
display: inline-block;
margin-right: 250px;
font-size: 12px;
color: rgba(34, 34, 34, 0.5);
font-weight: 400;
`;
const PriceName = styled.span`
display: inline-block;
margin-right: 150px;
font-size: 12px;
color: rgba(34, 34, 34, 0.5);
font-weight: 400;
`;
const DateName = styled.span`
display: inline-block;
font-size: 12px;
color: rgba(34, 34, 34, 0.5);
font-weight: 400;
`;
const RowSection = styled.div`
margin-top: 4px;
text-align: right;
`;
const Size = styled.span`
display: inline-block;
margin-right: 240px;
color: #222;
font-size: 12px;
`;
const Price = styled.span`
display: inline-block;
margin-right: 130px;
color: #222;
font-size: 12px;
`;
const Date = styled.span`
display: inline-block;
color: #222;
font-size: 12px;
`;
const OrderHistoryButton = styled.button`
border: 1px solid #d3d3d3;
margin-top: 40px;
background-color: #ffffff;
color: rgba(34, 34, 34, 0.8);
font-weight: 400;
padding: 0 18px;
width: 500px;
height: 42px;
border-radius: 12px;
font-size: 14px;
`;

const const [marketPriceData, setMarketPriceData] = useState([]);
useEffect(() => {
fetch(`/data/detailPageData.json`)
.then(res => res.json())
.then(data => setMarketPriceData(data.result.order_history.map(item => item.price));
}, []);

maybe you can use map in your object data result.
data.result.order_history.map((item)=>{
return item.price
}
That will only get de price property in in your array.
setMarketPriceData(data.result.order_history.map((item)=>{
return item.price
})

Related

useSelector rendering infinitely

When trying to set value equal to state value using useSelector value is reassigned again and again.
code below console logs quantities infintely
const quantities = useSelector((state) => state.cart.quantity) console.log(quantities)
Cart slice:
import { createSlice } from '#reduxjs/toolkit'
const cartSlice = createSlice({
name: 'cart',
initialState: {
products: [],
quantity: 0,
total: 0,
},
reducers: {
addProduct: (state, action) => {
state.quantity += 1
state.products.push(action.payload)
state.total += action.payload.price * action.payload.quantity
},
},
})
export const { addProduct } = cartSlice.actions
export default cartSlice.reducer
Store.js
import { configureStore, combineReducers } from '#reduxjs/toolkit'
import cartReducer from './cartRedux'
import userReducer from './userRedux'
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from 'redux-persist'
import storage from 'redux-persist/lib/storage'
const persistConfig = {
key: 'root',
version: 1,
storage,
}
const rootReducer = combineReducers({ user: userReducer, cart: cartReducer })
const persistedReducer = persistReducer(persistConfig, rootReducer)
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
})
export let persistor = persistStore(store)
entire component
import { Search, ShoppingCartOutlined } from '#material-ui/icons'
import React from 'react'
import styled from 'styled-components'
import { mobile } from '../responsive'
import { useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
import _ from 'underscore'
const Container = styled.div`
height: 60px;
${mobile({ height: '50px' })}
`
const Wrapper = styled.div`
padding: 10px 20px;
display: flex;
align-items: center;
justify-content: space-between;
${mobile({ padding: '10px 0px' })}
`
const Left = styled.div`
flex: 1;
display: flex;
align-items: center;
`
const Language = styled.span`
font-size: 14px;
cursor: pointer;
${mobile({ display: 'none' })}
`
const SearchContainer = styled.div`
border: 0.5px solid lightgray;
display: flex;
align-items: center;
margin-left: 25px;
padding: 5px;
`
const Input = styled.input`
border: none;
${mobile({ width: '50px' })}
`
const Center = styled.div`
flex: 1;
text-align: center;
`
const Logo = styled.h1`
font-weight: bold;
${mobile({ fontSize: '24px' })}
`
const Right = styled.div`
flex: 1;
display: flex;
align-items: center;
justify-content: flex-end;
${mobile({ flex: 2, justifyContent: 'center' })}
`
const MenuItem = styled.div`
font-size: 14px;
cursor: pointer;
margin-left: 25px;
${mobile({ fontSize: '12px', marginLeft: '10px' })}
`
const Navbar = () => {
const quantities = useSelector((state) => state.cart.quantity)
console.log(quantities)
return (
<Container>
<Wrapper>
<Left>
<Language>EN</Language>
<SearchContainer>
<Input placeholder='Search' />
<Search style={{ color: 'gray', fontSize: 16 }} />
</SearchContainer>
</Left>
<Center>
<Logo>LAMA.</Logo>
</Center>
<Right>
<MenuItem>REGISTER</MenuItem>
<MenuItem>SIGN IN</MenuItem>
<Link to='/cart'>
<MenuItem>
<Badge badgeContent={quantities} color='primary'>
<ShoppingCartOutlined />
</Badge>
</MenuItem>
</Link>
</Right>
</Wrapper>
</Container>
)
}
export default Navbar
Ancestor component
import styled from 'styled-components'
import Announcement from '../components/Announcement'
import Footer from '../components/Footer'
import Navbar from '../components/Navbar'
import Newsletter from '../components/Newsletter'
import { mobile } from '../responsive'
import { useState } from 'react'
import { useEffect } from 'react'
import { publicRequest } from '../requestMethods'
import { Link, useLocation } from 'react-router-dom'
const Container = styled.div``
const Wrapper = styled.div`
padding: 50px;
display: flex;
${mobile({ padding: '10px', flexDirection: 'column' })}
`
const ImgContainer = styled.div`
flex: 1;
`
const Image = styled.img`
width: 100%;
height: 90vh;
object-fit: cover;
${mobile({ height: '40vh' })}
`
const InfoContainer = styled.div`
flex: 1;
padding: 0px 50px;
${mobile({ padding: '10px' })}
`
const Title = styled.h1`
font-weight: 200;
`
const Desc = styled.p`
margin: 20px 0px;
`
const Price = styled.span`
font-weight: 100;
font-size: 40px;
`
const FilterContainer = styled.div`
width: 50%;
margin: 30px 0px;
display: flex;
justify-content: space-between;
${mobile({ width: '100%' })}
`
const Filter = styled.div`
display: flex;
align-items: center;
`
const FilterTitle = styled.span`
font-size: 20px;
font-weight: 200;
`
const FilterColor = styled.div`
width: 20px;
height: 20px;
border-radius: 50%;
background-color: ${(props) => props.color};
margin: 0px 5px;
cursor: pointer;
`
const FilterSize = styled.select`
margin-left: 10px;
padding: 5px;
`
const FilterSizeOption = styled.option``
const AddContainer = styled.div`
width: 50%;
display: flex;
align-items: center;
justify-content: space-between;
${mobile({ width: '100%' })}
`
const AmountContainer = styled.div`
display: flex;
align-items: center;
font-weight: 700;
`
const Amount = styled.span`
width: 30px;
height: 30px;
border-radius: 10px;
border: 1px solid teal;
display: flex;
align-items: center;
justify-content: center;
margin: 0px 5px;
`
const Button = styled.button`
padding: 15px;
border: 2px solid teal;
background-color: white;
cursor: pointer;
font-weight: 500;
&:hover {
background-color: #f8f4f4;
}
`
const Product = () => {
const location = useLocation()
const id = location.pathname.split('/')[2]
const [product, setProduct] = useState({})
const [quantity, setQuantity] = useState(1)
const [color, setColor] = useState('')
const [size, setSize] = useState('')
useEffect(() => {
const getProduct = async () => {
try {
const res = await publicRequest.get('/product/find/' + id)
setProduct(res.data)
} catch {}
}
getProduct()
})
const handleQuantity = (type) => {
if (type === 'dec') {
quantity > 1 && setQuantity(quantity - 1)
} else {
setQuantity(quantity + 1)
}
}
const handleClick = () => {
//update cart
}
return (
<Container>
<Navbar />
<Announcement />
<Wrapper>
<ImgContainer>
<Image src={product.img} />
</ImgContainer>
<InfoContainer>
<Title>{product.title}</Title>
<Desc>{product.desc}</Desc>
<Price>{product.Price}</Price>
<FilterContainer>
<Filter>
<FilterTitle>Color</FilterTitle>
{product.color?.map((c) => (
<FilterColor
color={c}
key={c}
onClick={() => {
setColor(c)
}}
/>
))}
</Filter>
<Filter>
<FilterTitle>Size</FilterTitle>
<FilterSize>
{product.size?.map((s) => (
<FilterSizeOption
key={s}
onChange={(e) => {
setSize(e.target.value)
}}
>
{s}
</FilterSizeOption>
))}
</FilterSize>
</Filter>
</FilterContainer>
<AddContainer>
<AmountContainer>
<Remove onClick={() => handleQuantity('dec')} />
<Amount>{quantity}</Amount>
<Add onClick={() => handleQuantity('inc')} />
</AmountContainer>
<Button onClick={handleClick}>ADD TO CART</Button>
</AddContainer>
</InfoContainer>
</Wrapper>
<Newsletter />
<Footer />
</Container>
)
}
export default Product
I am currently following an online tutorialenter code here but when he writes the same code it console.logs only once.
I even tried copy pasting his code still my code returns logs infinitely.
I just copied the ancestor component from the tutorial video github and it solved the problem but I don't know what was actually causing it if anyone can help
correct ancestor component
import styled from 'styled-components'
import Announcement from '../components/Announcement'
import Footer from '../components/Footer'
import Navbar from '../components/Navbar'
import Newsletter from '../components/Newsletter'
import { mobile } from '../responsive'
import { useLocation } from 'react-router-dom'
import { useEffect, useState } from 'react'
import { publicRequest } from '../requestMethods'
import { addProduct } from '../redux/cartRedux'
import { useDispatch } from 'react-redux'
const Container = styled.div``
const Wrapper = styled.div`
padding: 50px;
display: flex;
${mobile({ padding: '10px', flexDirection: 'column' })}
`
const ImgContainer = styled.div`
flex: 1;
`
const Image = styled.img`
width: 100%;
height: 90vh;
object-fit: cover;
${mobile({ height: '40vh' })}
`
const InfoContainer = styled.div`
flex: 1;
padding: 0px 50px;
${mobile({ padding: '10px' })}
`
const Title = styled.h1`
font-weight: 200;
`
const Desc = styled.p`
margin: 20px 0px;
`
const Price = styled.span`
font-weight: 100;
font-size: 40px;
`
const FilterContainer = styled.div`
width: 50%;
margin: 30px 0px;
display: flex;
justify-content: space-between;
${mobile({ width: '100%' })}
`
const Filter = styled.div`
display: flex;
align-items: center;
`
const FilterTitle = styled.span`
font-size: 20px;
font-weight: 200;
`
const FilterColor = styled.div`
width: 20px;
height: 20px;
border-radius: 50%;
background-color: ${(props) => props.color};
margin: 0px 5px;
cursor: pointer;
`
const FilterSize = styled.select`
margin-left: 10px;
padding: 5px;
`
const FilterSizeOption = styled.option``
const AddContainer = styled.div`
width: 50%;
display: flex;
align-items: center;
justify-content: space-between;
${mobile({ width: '100%' })}
`
const AmountContainer = styled.div`
display: flex;
align-items: center;
font-weight: 700;
`
const Amount = styled.span`
width: 30px;
height: 30px;
border-radius: 10px;
border: 1px solid teal;
display: flex;
align-items: center;
justify-content: center;
margin: 0px 5px;
`
const Button = styled.button`
padding: 15px;
border: 2px solid teal;
background-color: white;
cursor: pointer;
font-weight: 500;
&:hover {
background-color: #f8f4f4;
}
`
const Product = () => {
const location = useLocation()
const id = location.pathname.split('/')[2]
const [product, setProduct] = useState({})
const [quantity, setQuantity] = useState(1)
const [color, setColor] = useState('')
const [size, setSize] = useState('')
const dispatch = useDispatch()
useEffect(() => {
const getProduct = async () => {
try {
const res = await publicRequest.get('/product/find/' + id)
setProduct(res.data)
} catch {}
}
getProduct()
}, [id])
const handleQuantity = (type) => {
if (type === 'dec') {
quantity > 1 && setQuantity(quantity - 1)
} else {
setQuantity(quantity + 1)
}
}
const handleClick = () => {
dispatch(addProduct({ ...product, quantity, color, size }))
}
return (
<Container>
<Navbar />
<Announcement />
<Wrapper>
<ImgContainer>
<Image src={product.img} />
</ImgContainer>
<InfoContainer>
<Title>{product.title}</Title>
<Desc>{product.desc}</Desc>
<Price>$ {product.price}</Price>
<FilterContainer>
<Filter>
<FilterTitle>Color</FilterTitle>
{product.color?.map((c) => (
<FilterColor color={c} key={c} onClick={() => setColor(c)} />
))}
</Filter>
<Filter>
<FilterTitle>Size</FilterTitle>
<FilterSize onChange={(e) => setSize(e.target.value)}>
{product.size?.map((s) => (
<FilterSizeOption key={s}>{s}</FilterSizeOption>
))}
</FilterSize>
</Filter>
</FilterContainer>
<AddContainer>
<AmountContainer>
<Remove onClick={() => handleQuantity('dec')} />
<Amount>{quantity}</Amount>
<Add onClick={() => handleQuantity('inc')} />
</AmountContainer>
<Button onClick={handleClick}>ADD TO CART</Button>
</AddContainer>
</InfoContainer>
</Wrapper>
<Newsletter />
<Footer />
</Container>
)
}
export default Product

Renaming button.jsx makes entire react web unable to compile

i've been tasked with renaming a Button.jsx file for my react web app into 'v2_button.jsx' however when I do so it makes the entire web app unable to compile as there are many times where 'Button' is called but not 'v2_button'. My question is how do I make it so that I can update the name of the jsx file and update every instance where the original Button.jsx is called into 'v2_button'?
Button.jsx file:
import styled from 'styled-components';
const Button = styled.Button`
display: flex;
align-items: center;
justify-content: center;
height: 50px;
width: 300px;
background: ${(props) => {
let bg;
if (props.disabled) {
bg = props.theme.colors.disabled.background;
} else if (props.color === 'secondary') {
bg = props.theme.colors.primary.main;
} else if (props.color === 'danger') {
bg = props.theme.colors.danger.main;
} else {
bg = props.theme.colors.white;
}
return bg;
}};
font-family: ${(props) => props.theme.font.font3.new};
font-size: 18px;
font-weight: ${(props) => props.theme.fontWeight.heavy_900};
letter-spacing: 0.105em;
color: ${(props) => {
let fontColor;
if (props.color === 'secondary') {
fontColor = props.theme.colors.textPrimary.light;
} else {
fontColor = props.theme.colors.textPrimary.purple.dark;
}
return fontColor;
}};
padding: ${(props) => {
let padding;
if (props.size !== 's') {
padding = '0 39px';
}
return padding;
}};
border-radius: 40px;
border: ${(props) =>
props.disabled
? `1px solid ${props.theme.colors.disabled.border}`
: 'none'};
white-space: nowrap;
transition: background ${(props) => props.theme.animations.short} linear;
:hover {
background: ${(props) => {
let bg;
if (props.disabled) {
bg = props.theme.colors.disabled.background;
} else if (props.color === 'secondary') {
bg = props.theme.colors.primary.light;
} else if (props.color === 'danger') {
bg = props.theme.colors.danger.light;
} else {
bg = props.theme.colors.secondary.light;
}
return bg;
}};
cursor: pointer;
}
`;
export default Button;
Example where Button is called:
import styled from 'styled-components';
import Button from "../../Button";
export const Wrapper = styled.div`
display: flex;
flex-direction: column;
`;
export const Container = styled.div`
display: flex;
flex-direction: column;
`;
export const NameContainer = styled.div`
width: 100%;
display: flex;
align-content: space-between;
flex-direction: row;
font-style: normal;
font-weight: ${(props) => props.theme.fontWeight.med_500};
font-size: ${(props) => props.theme.fontSize.med_16};
`;
export const List = styled.div`
display: flex;
`;
export const FieldLabel = styled.label`
height: 36px;
color: ${(props) => props.theme.colors.white};
font-family: ${(props) => props.theme.font.font1.demi};
margin: 0 0 25px 0;
text-align: center;
font-style: normal;
font-weight: ${(props) => props.theme.fontWeight.heavy_800};
font-size: ${(props) => props.theme.fontSize.large_28};
line-height: 50px;
`;
export const Selected = styled.label`
width: 158px;
height: 40px;
margin: 0 10px 20px 10px;
padding-top: 10px;
padding-left: 20px;
font-size: ${(props) => props.theme.fontSize.med_20};
color: ${(props) => props.theme.colors.white};
font-family: ${(props) => props.theme.font.font1};
caret-color: ${(props) => props.theme.colors.textSecondary.main};
:focus {
outline: none;
}
:focus-within {
box-shadow: inset 0px 0px 2px 1px
${(props) => props.theme.colors.textSecondary.main};
}
::placeholder {
color: ${(props) => props.theme.colors.textPrimary.light};
}
background: ${(props) => props.theme.colors.primary.main};
border: ${(props) => props.theme.borders.textSecondary};
border-radius: 4px;
`;
export const AddFieldButton = styled(Button)`
margin: 30px;
font-size: ${(props) => props.theme.fontSize.med_20};
color: ${(props) => props.theme.colors.textSecondary.main};
background: none;
width: 1px;
text-align: center;
`;
Compiling error I receive after changing Button.jsx to v2_button.jsx:
https://imgur.com/a/kC0AdmG
The best thing is to renamed all the imports.
But a 'workaround' to renaming all the imports could be:
Keep the Button.jsx
Instead of exporting the default implementation, import the implementation from v2_button.jsx file and re-export it from the Button.jsx file.
Thus, every import of Button.tsx will actually refer to the implementation of v2_button.tsx file.
Example:
Button_v1.tsx
const Button_v1 = () => (
<>Button v1</>
);
export default Button_v1;
Button_v2.tsx
const Button_v2 = () => (
<>Button v2</>
);
export default Button_v2;
Since all other files reference Button_v1 and you don't want OR can't update the imports, you could do this:
Button_v1.tsx (after)
import Button_v2 from "./Button_v2"; // <-- ADDED THIS
const Button_v1 = () => (
<>Button v1</>
);
// export default Button_v1; // <-- COMMENTED THIS
export default Button_v2; // <-- ADDED THIS

react transition effect not work after async thunk

Although I have updated the todo status, the checkbox effect is not working correctly, as if no effect has been applied, what could be the reason for this? I don't think there is a problem with the api file, but the api request is taking a long time.I think it's because css doesn't render again, I can't think of anything else..
Thank you for helping
import React from "react";
import { useDispatch } from "react-redux";
import { toggleTodos } from "../redux/slice/thunkActions";
import styled from "styled-components";
const Content = styled.div`
color: #fff;
text-transform: capitalize;
`;
const Options = styled.div`
display: flex;
align-items: center;
justify-content: center;
gap: 2rem;
`;
const EditButton = styled.button`
cursor: pointer;
background-color: #ff6b81;
padding: 0.7rem 2rem;
color: #fff;
border-radius: 0.5rem;
font-weight: bold;
`;
const InputWrapper = styled.label`
position: relative;
`;
const Input = styled.input`
position: absolute;
left: -99999px;
top: -99999px;
&:checked + span {
background-color: #1890ff;
transition: 1s;
&:before {
left: calc(100% - 0.2rem);
transform: translateX(-100%);
}
}
`;
const Slider = styled.span`
display: flex;
width: 5rem;
height: 2.5rem;
cursor: pointer;
border-radius: 10rem;
background-color: #fcebb6;
transition: background-color 0.4s;
&:before {
content: "";
position: absolute;
top: 0.2rem;
left: 0.2rem;
width: 2.1rem;
height: 2.1rem;
border-radius: 2.1rem;
transition: 1s;
background-color: #fff;
}
`;
const Todo = ({ todo }) => {
const dispatch = useDispatch();
const handleChange = (todo) => {
dispatch(toggleTodos(todo));
};
return (
<li>
<Content>{todo.content}</Content>
<Options>
<EditButton type="button">Edit</EditButton>
<InputWrapper htmlFor={`todoContent${todo.id}`}>
<Input
id={`todoContent${todo.id}`}
type={"checkbox"}
onChange={() => handleChange(todo)}
checked={todo && todo.isCompleted}
/>
<Slider />
</InputWrapper>
</Options>
</li>
);
};
export default Todo;

In React, When I close the modal, I cannot scroll down/up

I am just getting started learning React with Function Component and Styled-Components. I created Modal Component and when I clicked the modal it shows up and I cannot scroll down/up(Background) but when I close the modal, I cannot scroll. I expect it should be work when I close the modal. Could you help me with what part something wrong?
const [showModal, setShowModal] = useState(false);
const [active, setActive] = useState(true);
const openModal = active => {
setShowModal(prev => !prev);
if (active) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = 'auto';
}
};
<ShowAllSizes>
<AllSize>모든 사이즈</AllSize>
<FaRegArrowAltCircleDown // isActive={active} onClick={()=> openModal}
className="FaIconModal"
/>
<Modal showModal={showModal} setShowModal={setShowModal} />
</ShowAllSizes>
I will leave the whole code just in case
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
import { FaRegArrowAltCircleDown } from 'react-icons/fa';
import { Modal } from './components/Modal';
export default function ColumnTop() {
const [showModal, setShowModal] = useState(false);
const [active, setActive] = useState(true);
const openModal = active => {
setShowModal(prev => !prev);
if (active) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = 'auto';
}
};
return (
<RightSideSection>
<ColumnTopSection>
<TitleBox>
<BrandName>Jordan</BrandName>
<EngName>Jordan 1 Retro High OG Bordeaux</EngName>
<KrName>조던 1 레트로 하이 OG 보르도</KrName>
</TitleBox>
<FigureWrap>
<DetailSize>
<SizeInKorean>사이즈</SizeInKorean>
<ShowAllSizes>
<AllSize>모든 사이즈</AllSize>
<FaRegArrowAltCircleDown
// isActive={active}
onClick={() => openModal}
className="FaIconModal"
/>
<Modal showModal={showModal} setShowModal={setShowModal} />
</ShowAllSizes>
</DetailSize>
<DetailPrice>
<TransactionPriceKorean>최근 거래가</TransactionPriceKorean>
<PriceInfo>
<CurrentPrice>248,000</CurrentPrice>
<PricePunctuation>6000원(-2.4%)</PricePunctuation>
</PriceInfo>
</DetailPrice>
<ButtonWrapper>
<Button>
<ButtonDivision>
<LeftSide>
<BtnTitle to="/order">구매</BtnTitle>
</LeftSide>
<RightSide>
<OrderPrice>23500원</OrderPrice>
<OrderStatusName>즉시 구매가</OrderStatusName>
</RightSide>
</ButtonDivision>
</Button>
<Button primary>
<ButtonDivision>
<LeftSide>
<BtnTitle to="/order">판매</BtnTitle>
</LeftSide>
<RightSide>
<OrderPrice>11500원</OrderPrice>
<OrderStatusName>즉시 판매가</OrderStatusName>
</RightSide>
</ButtonDivision>
</Button>
</ButtonWrapper>
</FigureWrap>
</ColumnTopSection>
</RightSideSection>
);
}
const ShowAllSizes = styled.div``;
const RightSideSection = styled.div`
padding-left: 40px;
`;
const ColumnTopSection = styled.div`
display: flex;
flex-direction: column;
`;
const TitleBox = styled.div`
display: flex;
flex-direction: column;
`;
const BrandName = styled.span`
display: inline-block;
vertical-align: top;
line-height: 19px;
padding-top: 1px;
margin-bottom: 9px;
font-size: 18px;
font-weight: 800;
border-bottom: 2px solid #222;
width: 61px;
height: 21px;
`;
const EngName = styled.span`
margin-bottom: 4px;
font-size: 18px;
font-weight: 400;
`;
const KrName = styled.span`
line-height: 17px;
font-size: 14px;
color: rgba(34, 34, 34, 0.5);
`;
const FigureWrap = styled.div`
width: 500px;
`;
const DetailSize = styled.div`
padding-top: 19px;
padding-bottom: 12px;
border-bottom: 1px solid #ebebeb;
`;
const SizeInKorean = styled.span`
padding-top: 4px;
display: inline-block;
line-height: 16px;
font-size: 13px;
color: rgba(34, 34, 34, 0.8);
`;
const AllSize = styled.span`
display: inline-block;
margin-right: 5px;
margin-left: 392px;
font-size: 18px;
`;
const FaIconModal = styled.button``;
const DetailPrice = styled.div`
display: flex;
margin-top: 4px;
`;
const TransactionPriceKorean = styled.span`
position: absolute;
width: 60px;
padding-top: 5px;
height: 7px;
font-size: 13px;
color: rgba(34, 34, 34, 0.8);
`;
const PriceInfo = styled.div`
display: flex;
flex-direction: column;
margin-left: 330px;
`;
const CurrentPrice = styled.span`
margin-left: 100px;
margin-top: 4px;
`;
const PricePunctuation = styled.span`
color: #31b46e;
margin-left: 110px;
`;
const ButtonWrapper = styled.div`
margin-top: 15px;
`;
const ButtonDivision = styled.div`
display: flex;
`;
const Button = styled.button`
background: ${props => (props.primary ? '#41B979' : '#EF6253')};
width: 235px;
height: 40px;
margin-right: 15px;
padding: 0 10px;
border: none;
border-radius: 5px;
`;
const LeftSide = styled.div`
margin-top: 3px;
left: 5px;
`;
const BtnTitle = styled(Link)`
font-weight: bold;
color: #fff;
text-decoration: none;
`;
const RightSide = styled.div`
margin-left: 10px;
border-left: 1px solid silver;
color: #fff;
`;
const OrderPrice = styled.div`
margin-left: 10px;
`;
const OrderStatusName = styled.div`
margin-left: 20px;
`;
This is my Modal Component
import React, { useRef, useState, useEffect, useCallback } from 'react';
import styled from 'styled-components';
import { MdClose } from 'react-icons/md';
export const Modal = ({ showModal, setShowModal }) => {
const modalRef = useRef();
const [detailPageData, setDetailPageData] = useState([]);
useEffect(() => {
fetch(`/data/detailPageData.json`)
.then(res => res.json())
.then(data => setDetailPageData(data.result.price_by_size));
}, []);
const closeModal = e => {
if (modalRef.current === e.target) {
setShowModal(false);
}
};
const keyPress = useCallback(
e => {
if (e.key === 'Escape' && showModal) {
setShowModal(false);
}
},
[setShowModal, showModal]
);
useEffect(() => {
document.addEventListener('keydown', keyPress);
return () => document.removeEventListener('keydown', keyPress);
}, [keyPress]);
// console.log(setDetailPageData);
return (
<div>
{showModal ? (
<Background onClick={closeModal} ref={modalRef}>
<ModalWrapper showModal={showModal}>
<SizeModalContent>
<Title>사이즈</Title>
<ButtonWrapper>
{detailPageData.map(({ id, title, price }) => {
return (
<Button key={id}>
<Size>{title}</Size>
<Price>{price}</Price>
</Button>
);
})}
</ButtonWrapper>
</SizeModalContent>
<CloseModalButton
aria-label="Close modal"
onClick={() => setShowModal(prev => !prev)}
/>
</ModalWrapper>
</Background>
) : null}
</div>
);
};
const Background = styled.div`
position: fixed;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
left: -0px;
top: -0px;
background: rgba(0, 0, 0, 0.8);
z-index: 10;
`;
const ModalWrapper = styled.div`
width: 400px;
height: 400px;
background: #fff;
color: #000;
border-radius: 10px;
`;
const SizeModalContent = styled.div`
margin-left: 20px;
margin-right: 20px;
`;
const Title = styled.div`
margin: 15px;
font-weight: 700;
color: #000;
text-align: center;
`;
const ButtonWrapper = styled.div`
margin: 10px 0px;
display: grid;
grid-template-columns: repeat(3, 33%);
`;
const Button = styled.button`
width: 100px;
height: 35px;
margin-left: 5px;
margin-bottom: 5px;
border: 1px solid #d3d3d3;
border-radius: 10px;
background-color: #fff;
`;
const Size = styled.span`
display: block;
font-weight: 700px;
`;
const Price = styled.span`
color: red;
`;
const CloseModalButton = styled(MdClose)`
cursor: pointer;
position: absolute;
top: 350px;
right: 800px;
font-size: 20px;
/* top: -50px;
right: -360px;
width: 32px;
height: 32px; */
`;
Edit1: Copy and Past my Modal.js

New to React: Using an async/await fetch request to return userData into a component

New to React:I am using async/await to return user data to a component after login. However, my fetch call is firing prior to the login process. What am I doing incorrectly? Thank you in advance.
import React from 'react'
import { LoginButton } from '../FormElements/LoginButton';
import styled from 'styled-components'
import eglogo from '../../../assets/images/eglogo.png'
import genericUser from '../../../assets/images/generic-user.png'
import Link from 'next/link'
// ********************************************************
// ****** UserProfile Element Definitions
// ****** (styled-components) -- EricGuest
// ********************************************************
const ProfileContainer = styled.div`
padding: 15px 0 25px 0;
display: inline-block;
width: 50%;`
const ProfileImageContainer = styled.div`
width: 75px;
height: 75px;
background: #303e48;
border: 3px solid #4d6373;
border-radius: 50%;
padding: 7px;
margin:0 10px 0 35px;
float: left;`
const ProfileImage = styled.img`
width: 100%;
height: 100%;
padding: 8%;
background: #4d6373;
border-radius: 50%;
margin: 0 auto;`
const ProfileName = styled.h2`
color: rgba(255,255,255,.75);
font-family: Helvetica;
font-weight: normal;
font-size: 1.25em;
text-align: left;
margin: 13px 0 0 0;`
const LoginText = styled.h3`
color: rgba(255,255,255,.75);
font-family: Helvetica;
font-weight: normal;
font-size: .75em;
text-align: left;
margin: 00033px;
padding-top: 13px;
clear: left;`
const NameSpan = styled.span`
margin-right: 10px;`
const ProfileEmail = styled.a`
text-align: left;
color: rgba(255,255,255,.75);
text-decoration: none;
transition:.3s all ease-in-out;
&:hover{
color: #1d9add;
text-decoration: none;
}`
export const judgeSoul = () => {
window.location.replace('http://localhost:8081/auth/google?returnURL=http://localhost:3000');
}
export class UserProfile extendsReact.Component < Props > {
constructor(props: Props) {
super(props);
this.state = {
loading: true,
profile: []
};
};
async componentDidMount() {
const url = 'http://localhost:8081/auth/me';
const response = await fetch(url, {
method: 'GET',
credentials: 'include'
});
const userData = await response.json();
this.setState({
profile: userData,
loading: false
});
};
render = () => (
<div>
{this.state.loading || !this.state.profile ? (
<ProfileContainer>
<ProfileImageContainer>
<ProfileImage src={genericUser} />
</ProfileImageContainer>
<LoginText>Please Log In</LoginText>
<LoginButton />
</ProfileContainer>
) : (
<ProfileContainer>
<ProfileImageContainer>
<ProfileImage src={eglogo} />
</ProfileImageContainer>
<ProfileName>
<NameSpan>
{this.state.profile.firstName}
</NameSpan>
{this.state.profile.lastName}
</ProfileName>
<ProfileEmail href="/">
{this.state.profile.email}
</ProfileEmail>
<LoginButton />
</ProfileContainer>
)}
</div>
);
}
there is an issue with your condition.
just use
this.state.loading
instead of
this.state.loading || !this.state.profile

Resources