英文:
How to pass the value of a variable from one component to another in React
问题
"CartContainer.jsx" 用于计算用户添加到购物车中的产品的成本。
"PaymentContainer.jsx" 这个组件与 Stripe.js 一起使用,并具有一个 "amount" 变量。
我希望从 "CartContainer.jsx" 中获取项目的总成本,并将其分配给 "PaymentContainer.jsx" 中的 "amount" 变量。
感谢大家
英文:
I use two components:
-"CartContainer.jsx" to count the cost of products that user has added to the cart.
UPDATED:
import React, { useEffect, useState } from "react";
import { useStateValue } from "../context/StateProvider";
import { actionType } from "../context/reducer";
//another imports
import { Link } from "react-router-dom";
import PaymentContainer from "./PaymentContainer";
const CartContainer = () => {
const [{ cartShow, cartItems, user }, dispatch] = useStateValue();
const [flag, setFlag] = useState(1);
const [tot, setTot] = useState(0);
//another methods
useEffect(() => {
let totalPrice = cartItems.reduce(function (accumulator, item) {
return accumulator + item.qty * item.price;
}, 0);
setTot(totalPrice);
console.log(tot);
}, [tot, flag]);
//another methods
return (
<motion.div initial... animate... exit... class...">
//something code
{/* bottom section */}
//something code
{/* cart total section code */}
<div class...>
<div class...>
<p class...>Sub Total</p>
<p class...>$ {tot}</p>
</div>
<div class...>
<p class...>Delivery</p>
<p class...>$ 2.5</p>
</div>
//another code
<div class...>
<p class...>Total</p>
<p class...>${tot + 2.5}</p>
</div>
{user ? (
<Link to={'/payment'}> *//it's link to PaymentContainer*
<motion.button whileTap={{ scale: 0.8 }} type="button" class...>Check Out</motion.button>
</Link>
) : (
//another code
)}
</div>
<div>
<PaymentContainer totalAmount={tot} />
</div>
</div>
) : (
//another code
)}
</motion.div>
);
};
export default CartContainer;
-"PaymentContainer.jsx" this component works with Stripe.js and has a "amount"-variable.
UPDATED:
import React from "react";
const PaymentContainer = ({totalAmount}) => {
const containerAmount = totalAmount;
console.log(totalAmount);
return (
<div>
<h2>Total: {containerAmount}</h2>
</div>
);
};
export default PaymentContainer;
I want the total cost of items from "CartContainer.jsx" to be assigned to the "amount"-variable in "PaymentContainer.jsx"
Thank you all
I found a similar question in this forum and tried to apply the solution, but I couldn't.
I tried to adapt this code in file "PaymentContainer.jsx"
const handleInputChange = (e) => {
const valueFilterActive = document.getElementById("activeFilter").value;
const valueFilterName = document.getElementById("bussFilter").value;
// this will set `inputValues` variable to be an object with `valueFilterActive` and `valueFilterName` properties
setInputValues({valueFilterActive, valueFilterName})
alert(valueFilterName+valueFilterActive);
};
UPDATED: App.js
import React, { useEffect } from "react";
import { Route, Routes } from "react-router-dom";
import { AnimatePresence } from "framer-motion";
import { CreateContainer, Header, MainContainer, PaymentContainer } from "./components";
import { useStateValue } from "./context/StateProvider";
import { getAllFoodItems } from "./utils/firebaseFunctions";
import { actionType } from "./context/reducer";
const App = () => {
const [{foodItems}, dispatch] = useStateValue();
const fetchData = async () => {
await getAllFoodItems().then(data => {
dispatch({
type : actionType.SET_FOOD_ITEMS,
foodItems : data,
});
});
};
useEffect(() => {
fetchData();
}, []);
return (
<AnimatePresence mode="wait">
<div class...>
<Header />
<main class...>
<Routes>
<Route path="/*" element={<MainContainer />} />
<Route path="/createItem" element={<CreateContainer />} />
//here PaymentContainer
<Route path="/payment" element={<PaymentContainer />} /> here PaymentContainer
//here PaymentContainer
</Routes>
</main>
</div>
</AnimatePresence>
);
}
export default App
UPDATED:
Browser console when I add products to cart and get the amount but when I go to "Payment Container" by "Link" the value is undefined.
答案1
得分: 3
在React中,你可以通过props或全局状态将数据传递给其他组件,因此一种方法是在CartContainer.jsx
内部渲染PaymentContainer.jsx
并传递数据。
例如:
import React, { useEffect, useState } from "react";
// 其他导入项
import PaymentContainer from "./PaymentContainer";
const CartContainer = () => {
const [tot, setTot] = useState(0);
// 你的先前数据
return (
// 你的先前内容
<PaymentContainer totalAmount={tot} />
)
}
export default CartContainer;
你的支付容器还需要接收props以查看:
const PaymentContainer = ({totalAmount}) => {
console.log(totalAmount);
// 你的先前内容
return (
// 你的先前内容
)
}
参考链接:https://reactjs.org/docs/components-and-props.html
英文:
in React, you can pass data to other components via props or global state, so one way would be to render the PaymentContainer.jsx
inside the CartContainer.jsx
and pass data to it.
For example:
import React, { useEffect, useState } from "react";
// your other imports
import PaymentContainer from "./PaymentContainer";
const CartContainer = () => {
const [tot, setTot] = useState(0);
// your previous data
return (
// your previous stuff
<PaymentContainer totalAmount={tot} />
)
}
export default CartContainer
Your payment Container would also need to receive the props to view
const PaymentContainer = ({totalAmount}) => {
console.log(totalAmount)
// your previous stuff
return (
// your previous stuff
)
}
Reference: https://reactjs.org/docs/components-and-props.html
答案2
得分: 2
问题
您在至少两个地方渲染了PaymentContainer
组件,一次在CartContainer
中,传递了一个totalAmount
属性:
<div>
<PaymentContainer totalAmount={tot} />
</div>
另一次在路由中,没有传递任何属性:
<Route path="/payment" element={<PaymentContainer />} />
在通过CartContainer
中的Link
导航到的第二个位置时,total
未定义。
解决方案
不清楚为什么要在两个地方不同地渲染PaymentContainer
,所以我会忽略这一部分。如果您想在一个路由中渲染PaymentContainer
并传递数据给它,您应该通过链接在路由状态中传递它。
tot
状态实际上也是不必要的,因为它是从实际的 cartItems
状态派生出来的。在React状态中存储派生状态通常被认为是React中的反模式。您应该在每个渲染周期内计算和使用它。
请注意,在几乎所有使用 useState/useEffect
钩子组合的用例中,您实际上应该使用 useMemo
钩子来计算和缓存一个稳定的值引用。
示例:
const totalPrice = cartItems.reduce(function (accumulator, item) {
return accumulator + item.qty * item.price;
}, 0);
const totalPrice = React.useMemo(() => {
return cartItems.reduce(function (accumulator, item) {
return accumulator + item.qty * item.price;
}, 0);
}, [cartItems]);
代码示例:
const CartContainer = () => {
const [{ cartShow, cartItems, user }, dispatch] = useStateValue();
const [flag, setFlag] = useState(1);
// 其他方法
const totalAmount = React.useMemo(() => {
return cartItems.reduce(function (accumulator, item) {
return accumulator + item.qty * item.price;
}, 0);
}, [cartItems]);
// 其他方法
return (
<motion.div initial... animate... exit... class="...">
...
{user ? (
<Link to="/payment" state={{ totalAmount }}> // <-- 在状态中传递totalAmount
<motion.button
whileTap={{ scale: 0.8 }}
type="button"
class...
>
Check Out
</motion.button>
</Link>
) : (
//其他代码
)}
...
<PaymentContainer totalAmount={totalAmount} />
...
</motion.div>
);
};
import React from "react";
import { useLocation } from 'react-router-dom';
const PaymentContainer = ({ totalAmount }) => {
const { state } = useLocation();
const containerAmount = state.totalAmount || totalAmount || 0;
React.useEffect(() => {
console.log(totalAmount);
}, [totalAmount]);
return (
<div>
<h2>Total: {containerAmount}</h2>
</div>
);
};
英文:
Issue
You are rendering the PaymentContainer
component in at least two places, once in CartContainer
where a totalAmount
prop is passed:
<div>
<PaymentContainer totalAmount={tot} />
</div>
And once in the routes where no props are passed:
<Route path="/payment" element={<PaymentContainer />} />
It is the second that when navigated to by the Link
in CartContainer
that the total is undefined.
A Solution
It's not clear why you are rendering PaymentContainer
in two places differently, so I'll ignore this part. If you want to render PaymentContainer
on a route and pass data to it you will pass it in route state via the link.
The tot
state is actually also unnecessary since it's derived "state" from the actual cartItems
state. It's generally considered a React anti-pattern to store derived state in React state. You should compute and use it locally per render cycle.
Note that in almost 100% of the use cases where you find yourself coding a useState/useEffect
hook combo what you really should use is the useMemo
hook to compute and memoize a stable value reference.
Examples:
const totalPrice = cartItems.reduce(function (accumulator, item) {
return accumulator + item.qty * item.price;
}, 0);
const totalPrice = React.useMemo(() => {
return cartItems.reduce(function (accumulator, item) {
return accumulator + item.qty * item.price;
}, 0);
}, [cartItems]);
Code Example:
const CartContainer = () => {
const [{ cartShow, cartItems, user }, dispatch] = useStateValue();
const [flag, setFlag] = useState(1);
// another methods
const totalAmount = React.useMemo(() => {
return cartItems.reduce(function (accumulator, item) {
return accumulator + item.qty * item.price;
}, 0);
}, [cartItems]);
// another methods
return (
<motion.div initial... animate... exit... class...">
...
{user ? (
<Link to="/payment" state={{ totalAmount }}> // <-- pass totalAmount in state
<motion.button
whileTap={{ scale: 0.8 }}
type="button"
class...
>
Check Out
</motion.button>
</Link>
) : (
//another code
)}
...
<PaymentContainer totalAmount={totalAmount} />
...
</motion.div>
);
};
import React from "react";
import { useLocation } from 'react-router-dom';
const PaymentContainer = ({ totalAmount }) => {
const { state } = useLocation();
const containerAmount = state.totalAmount || totalAmount || 0;
React.useEffect(() => {
console.log(totalAmount);
}, [totalAmount]);
return (
<div>
<h2>Total: {containerAmount}</h2>
</div>
);
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论