Reactjs 链接React.useffect依赖项会导致重新渲染缓慢
我正在创建一个屏幕来“购买”加密,我已经按照所附的图片组织了组件。当我更改EUR输入量时,我希望计算速度非常快,因为不涉及API调用(只涉及基本的数学运算)。由于我正在将useEffect状态和更新函数从BuyScreen向下传递到CurrencyWidget和FeeSummary作为道具,所以我需要使用(据我所知)useEffect和对值的依赖关系来确保我有最后一个更新的值 问题在于UI更新()的速度有多慢,因为我正在更改几个useEffect挂钩以确保我拥有所有更新的值。我的代码中是否有可以改进的地方来解决这个问题 BuyScreen.jsReactjs 链接React.useffect依赖项会导致重新渲染缓慢,reactjs,react-native,react-hooks,use-effect,use-state,Reactjs,React Native,React Hooks,Use Effect,Use State,我正在创建一个屏幕来“购买”加密,我已经按照所附的图片组织了组件。当我更改EUR输入量时,我希望计算速度非常快,因为不涉及API调用(只涉及基本的数学运算)。由于我正在将useEffect状态和更新函数从BuyScreen向下传递到CurrencyWidget和FeeSummary作为道具,所以我需要使用(据我所知)useEffect和对值的依赖关系来确保我有最后一个更新的值 问题在于UI更新()的速度有多慢,因为我正在更改几个useEffect挂钩以确保我拥有所有更新的值。我的代码中是否有可以
const calculateTotalBuyTransactionAmount = (
buySourceAmount,
cryptoBuyPrice
) => {
return (buySourceAmount / cryptoBuyPrice).toFixed(8);
};
const calculateSubtotal = (amount, fees) => {
return (amount - fees).toFixed(2);
};
const BuyScreen = (props) => {
const [buySourceAmount, setBuySourceAmount] = useState(0.0);
const [buyDestinationAmount, setBuyDestinationAmount] = useState(0.0);
const [feeAmount, setFeeAmount] = useState(0.0);
const [feeSubTotalAmount, setFeeSubTotalAmount] = useState(0.0);
const [cryptoBuyPrice, setCryptoBuyPrice] = useState(
pricesMock[0].values.prices.EUR.buy
);
useEffect(() => {
setFeeAmount((buySourceAmount * 0.05).toFixed(2));
}, [buySourceAmount]);
useEffect(() => {
setFeeSubTotalAmount(calculateSubtotal(buySourceAmount, feeAmount));
}, [feeAmount]);
useEffect(() => {
setBuyDestinationAmount(
calculateTotalBuyTransactionAmount(feeSubTotalAmount, cryptoBuyPrice)
);
}, [feeSubTotalAmount]);
console.log("Rendering BuyScreen");
return (
<SafeAreaView style={{ flex: 1 }}>
<Container>
<Content padder>
<View>
<CurrencyWidget
currencyName={balancesMock.values.currencyBalances[0].name}
currencyCode={balancesMock.values.currencyBalances[0].code}
balance={balancesMock.values.currencyBalances[0].total}
inputAmount={buySourceAmount}
setInputAmount={(amount) => {
setBuySourceAmount(amount);
}}
autofocus
/>
<FeesSummary
feeAmount={feeAmount}
feeSubTotalAmount={feeSubTotalAmount}
/>
<RealTimeCryptoPriceWidget
currencyCode={balancesMock.values.cryptoBalances[0].code}
cryptoBuyPrice={cryptoBuyPrice}
/>
<CurrencyWidget
currencyName={balancesMock.values.cryptoBalances[0].name}
currencyCode={balancesMock.values.cryptoBalances[0].code}
balance={balancesMock.values.cryptoBalances[0].total}
inputAmount={buyDestinationAmount}
destinationCurrency
/>
</View>
<View>
<LoadingSpinner area="buy-button">
<Button
block
primary-light
style={{
marginBottom: 16,
}}
>
<Text>Buy {balancesMock.values.cryptoBalances[0].name}</Text>
</Button>
</LoadingSpinner>
</View>
</Content>
</Container>
</SafeAreaView>
);
};
const CurrencyWidget = (props) => {
console.log("Rendering CurrencyWidget");
return (
<Grid>
<Col>
<Text notification-light>
{props.currencyName} ({props.currencyCode})
</Text>
<Text label-light style={styles.balanceAmount}>
Balance: {props.currencyCode} {props.balance}
</Text>
</Col>
<Col style={{ alignItems: "flex-end", justifyContent: "flex-start" }}>
<Item regular>
<Input
transactionAmount
keyboardType="numeric"
placeholder="0"
editable={!props.destinationCurrency}
autoFocus={props.autofocus}
value={String(props.inputAmount)}
onChangeText={(amount) => {
console.log("amount: ", amount);
amount === ""
? props.setInputAmount("0")
: props.setInputAmount(amount);
}}
/>
</Item>
</Col>
</Grid>
);
};
const FeesSummary = props => {
const sellPageFees = () => {
return (
<Grid style={styles.verticalPadding}>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Subtotal</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>
EUR {props.feeSubTotalAmount}
</Text>
</Col>
</Row>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Fees</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>EUR {props.feeAmount}</Text>
</Col>
</Row>
</Grid>
);
};
const buyPageFees = () => {
return (
<Grid style={styles.verticalPadding}>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Fees</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>EUR {props.feeAmount}</Text>
</Col>
</Row>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Subtotal</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>
EUR {props.feeSubTotalAmount}
</Text>
</Col>
</Row>
</Grid>
);
};
console.log("Rendering FeeSummary");
return props.isSellPage ? sellPageFees() : buyPageFees();
};
<CurrencyWidget
currencyName={balancesMock.values.currencyBalances[0].name}
currencyCode={balancesMock.values.currencyBalances[0].code}
balance={balancesMock.values.currencyBalances[0].total}
inputAmount={buySourceAmount}
setInputAmount={handleBuySourceAmount}
autofocus
/>
const calculateTotalBuyTransactionMount=(
buySourceAmount,
加密买价
) => {
返回(buySourceAmount/cryptoBuyPrice).toFixed(8);
};
const calculateSubtotal=(金额、费用)=>{
回报(金额-费用)。固定(2);
};
const BuyScreen=(道具)=>{
const[buySourceAmount,setBuySourceAmount]=useState(0.0);
const[buyDestinationAmount,setBuyDestinationAmount]=useState(0.0);
const[feeamunit,setfeeamunit]=useState(0.0);
const[FeeSetottotalAmount,setFeeSetottotalAmount]=useState(0.0);
const[cryptoBuyPrice,setCryptoBuyPrice]=useState(
pricesMock[0].values.prices.EUR.buy
);
useffect(()=>{
设定值((buySourceAmount*0.05).toFixed(2));
},[buySourceAmount]);
useffect(()=>{
setFeeSubTotalAmount(计算Subtotal(buySourceAmount,feeAmount));
},[金额];
useffect(()=>{
目的地山(
CalculateTotalBuyTransactionMount(feeSubTotalAmount,cryptoBuyPrice)
);
},[小计金额];
console.log(“渲染屏幕”);
返回(
{
收入来源金额(金额);
}}
自动对焦
/>
购买{balancesMock.values.cryptoBalances[0].name}
);
};
CurrencyWidget.js
const calculateTotalBuyTransactionAmount = (
buySourceAmount,
cryptoBuyPrice
) => {
return (buySourceAmount / cryptoBuyPrice).toFixed(8);
};
const calculateSubtotal = (amount, fees) => {
return (amount - fees).toFixed(2);
};
const BuyScreen = (props) => {
const [buySourceAmount, setBuySourceAmount] = useState(0.0);
const [buyDestinationAmount, setBuyDestinationAmount] = useState(0.0);
const [feeAmount, setFeeAmount] = useState(0.0);
const [feeSubTotalAmount, setFeeSubTotalAmount] = useState(0.0);
const [cryptoBuyPrice, setCryptoBuyPrice] = useState(
pricesMock[0].values.prices.EUR.buy
);
useEffect(() => {
setFeeAmount((buySourceAmount * 0.05).toFixed(2));
}, [buySourceAmount]);
useEffect(() => {
setFeeSubTotalAmount(calculateSubtotal(buySourceAmount, feeAmount));
}, [feeAmount]);
useEffect(() => {
setBuyDestinationAmount(
calculateTotalBuyTransactionAmount(feeSubTotalAmount, cryptoBuyPrice)
);
}, [feeSubTotalAmount]);
console.log("Rendering BuyScreen");
return (
<SafeAreaView style={{ flex: 1 }}>
<Container>
<Content padder>
<View>
<CurrencyWidget
currencyName={balancesMock.values.currencyBalances[0].name}
currencyCode={balancesMock.values.currencyBalances[0].code}
balance={balancesMock.values.currencyBalances[0].total}
inputAmount={buySourceAmount}
setInputAmount={(amount) => {
setBuySourceAmount(amount);
}}
autofocus
/>
<FeesSummary
feeAmount={feeAmount}
feeSubTotalAmount={feeSubTotalAmount}
/>
<RealTimeCryptoPriceWidget
currencyCode={balancesMock.values.cryptoBalances[0].code}
cryptoBuyPrice={cryptoBuyPrice}
/>
<CurrencyWidget
currencyName={balancesMock.values.cryptoBalances[0].name}
currencyCode={balancesMock.values.cryptoBalances[0].code}
balance={balancesMock.values.cryptoBalances[0].total}
inputAmount={buyDestinationAmount}
destinationCurrency
/>
</View>
<View>
<LoadingSpinner area="buy-button">
<Button
block
primary-light
style={{
marginBottom: 16,
}}
>
<Text>Buy {balancesMock.values.cryptoBalances[0].name}</Text>
</Button>
</LoadingSpinner>
</View>
</Content>
</Container>
</SafeAreaView>
);
};
const CurrencyWidget = (props) => {
console.log("Rendering CurrencyWidget");
return (
<Grid>
<Col>
<Text notification-light>
{props.currencyName} ({props.currencyCode})
</Text>
<Text label-light style={styles.balanceAmount}>
Balance: {props.currencyCode} {props.balance}
</Text>
</Col>
<Col style={{ alignItems: "flex-end", justifyContent: "flex-start" }}>
<Item regular>
<Input
transactionAmount
keyboardType="numeric"
placeholder="0"
editable={!props.destinationCurrency}
autoFocus={props.autofocus}
value={String(props.inputAmount)}
onChangeText={(amount) => {
console.log("amount: ", amount);
amount === ""
? props.setInputAmount("0")
: props.setInputAmount(amount);
}}
/>
</Item>
</Col>
</Grid>
);
};
const FeesSummary = props => {
const sellPageFees = () => {
return (
<Grid style={styles.verticalPadding}>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Subtotal</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>
EUR {props.feeSubTotalAmount}
</Text>
</Col>
</Row>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Fees</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>EUR {props.feeAmount}</Text>
</Col>
</Row>
</Grid>
);
};
const buyPageFees = () => {
return (
<Grid style={styles.verticalPadding}>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Fees</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>EUR {props.feeAmount}</Text>
</Col>
</Row>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Subtotal</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>
EUR {props.feeSubTotalAmount}
</Text>
</Col>
</Row>
</Grid>
);
};
console.log("Rendering FeeSummary");
return props.isSellPage ? sellPageFees() : buyPageFees();
};
<CurrencyWidget
currencyName={balancesMock.values.currencyBalances[0].name}
currencyCode={balancesMock.values.currencyBalances[0].code}
balance={balancesMock.values.currencyBalances[0].total}
inputAmount={buySourceAmount}
setInputAmount={handleBuySourceAmount}
autofocus
/>
const CurrencyWidget=(道具)=>{
log(“呈现CurrencyWidget”);
返回(
{props.currencyName}({props.currencyCode})
余额:{props.currencyCode}{props.Balance}
{
控制台日志(“金额:”,金额);
金额==“”
?道具设置输入量(“0”)
:道具设置输入量(金额);
}}
/>
);
};
feesummmary.js
const calculateTotalBuyTransactionAmount = (
buySourceAmount,
cryptoBuyPrice
) => {
return (buySourceAmount / cryptoBuyPrice).toFixed(8);
};
const calculateSubtotal = (amount, fees) => {
return (amount - fees).toFixed(2);
};
const BuyScreen = (props) => {
const [buySourceAmount, setBuySourceAmount] = useState(0.0);
const [buyDestinationAmount, setBuyDestinationAmount] = useState(0.0);
const [feeAmount, setFeeAmount] = useState(0.0);
const [feeSubTotalAmount, setFeeSubTotalAmount] = useState(0.0);
const [cryptoBuyPrice, setCryptoBuyPrice] = useState(
pricesMock[0].values.prices.EUR.buy
);
useEffect(() => {
setFeeAmount((buySourceAmount * 0.05).toFixed(2));
}, [buySourceAmount]);
useEffect(() => {
setFeeSubTotalAmount(calculateSubtotal(buySourceAmount, feeAmount));
}, [feeAmount]);
useEffect(() => {
setBuyDestinationAmount(
calculateTotalBuyTransactionAmount(feeSubTotalAmount, cryptoBuyPrice)
);
}, [feeSubTotalAmount]);
console.log("Rendering BuyScreen");
return (
<SafeAreaView style={{ flex: 1 }}>
<Container>
<Content padder>
<View>
<CurrencyWidget
currencyName={balancesMock.values.currencyBalances[0].name}
currencyCode={balancesMock.values.currencyBalances[0].code}
balance={balancesMock.values.currencyBalances[0].total}
inputAmount={buySourceAmount}
setInputAmount={(amount) => {
setBuySourceAmount(amount);
}}
autofocus
/>
<FeesSummary
feeAmount={feeAmount}
feeSubTotalAmount={feeSubTotalAmount}
/>
<RealTimeCryptoPriceWidget
currencyCode={balancesMock.values.cryptoBalances[0].code}
cryptoBuyPrice={cryptoBuyPrice}
/>
<CurrencyWidget
currencyName={balancesMock.values.cryptoBalances[0].name}
currencyCode={balancesMock.values.cryptoBalances[0].code}
balance={balancesMock.values.cryptoBalances[0].total}
inputAmount={buyDestinationAmount}
destinationCurrency
/>
</View>
<View>
<LoadingSpinner area="buy-button">
<Button
block
primary-light
style={{
marginBottom: 16,
}}
>
<Text>Buy {balancesMock.values.cryptoBalances[0].name}</Text>
</Button>
</LoadingSpinner>
</View>
</Content>
</Container>
</SafeAreaView>
);
};
const CurrencyWidget = (props) => {
console.log("Rendering CurrencyWidget");
return (
<Grid>
<Col>
<Text notification-light>
{props.currencyName} ({props.currencyCode})
</Text>
<Text label-light style={styles.balanceAmount}>
Balance: {props.currencyCode} {props.balance}
</Text>
</Col>
<Col style={{ alignItems: "flex-end", justifyContent: "flex-start" }}>
<Item regular>
<Input
transactionAmount
keyboardType="numeric"
placeholder="0"
editable={!props.destinationCurrency}
autoFocus={props.autofocus}
value={String(props.inputAmount)}
onChangeText={(amount) => {
console.log("amount: ", amount);
amount === ""
? props.setInputAmount("0")
: props.setInputAmount(amount);
}}
/>
</Item>
</Col>
</Grid>
);
};
const FeesSummary = props => {
const sellPageFees = () => {
return (
<Grid style={styles.verticalPadding}>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Subtotal</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>
EUR {props.feeSubTotalAmount}
</Text>
</Col>
</Row>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Fees</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>EUR {props.feeAmount}</Text>
</Col>
</Row>
</Grid>
);
};
const buyPageFees = () => {
return (
<Grid style={styles.verticalPadding}>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Fees</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>EUR {props.feeAmount}</Text>
</Col>
</Row>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Subtotal</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>
EUR {props.feeSubTotalAmount}
</Text>
</Col>
</Row>
</Grid>
);
};
console.log("Rendering FeeSummary");
return props.isSellPage ? sellPageFees() : buyPageFees();
};
<CurrencyWidget
currencyName={balancesMock.values.currencyBalances[0].name}
currencyCode={balancesMock.values.currencyBalances[0].code}
balance={balancesMock.values.currencyBalances[0].total}
inputAmount={buySourceAmount}
setInputAmount={handleBuySourceAmount}
autofocus
/>
const FeesSummary=props=>{
const sellPageFees=()=>{
返回(
小计
欧元{props.fee小计金额}
费用
欧元{props.feeamunit}
);
};
const buyPageFees=()=>{
返回(
费用
欧元{props.feeamunit}
小计
欧元{props.fee小计金额}
);
};
控制台日志(“摘要”);
return props.isSellPage?sellPageFees():buyPageFees();
};
对于在同一问题中运行的任何人,我设法通过将状态更新与更新字段所需的计算分开处理来解决,请参阅以下代码:
BuyScreen.js
const calculateTotalBuyTransactionAmount = (
buySourceAmount,
cryptoBuyPrice
) => {
return (buySourceAmount / cryptoBuyPrice).toFixed(8);
};
const calculateSubtotal = (amount, fees) => {
return (amount - fees).toFixed(2);
};
const BuyScreen = (props) => {
const [buySourceAmount, setBuySourceAmount] = useState(0.0);
const [buyDestinationAmount, setBuyDestinationAmount] = useState(0.0);
const [feeAmount, setFeeAmount] = useState(0.0);
const [feeSubTotalAmount, setFeeSubTotalAmount] = useState(0.0);
const [cryptoBuyPrice, setCryptoBuyPrice] = useState(
pricesMock[0].values.prices.EUR.buy
);
useEffect(() => {
setFeeAmount((buySourceAmount * 0.05).toFixed(2));
}, [buySourceAmount]);
useEffect(() => {
setFeeSubTotalAmount(calculateSubtotal(buySourceAmount, feeAmount));
}, [feeAmount]);
useEffect(() => {
setBuyDestinationAmount(
calculateTotalBuyTransactionAmount(feeSubTotalAmount, cryptoBuyPrice)
);
}, [feeSubTotalAmount]);
console.log("Rendering BuyScreen");
return (
<SafeAreaView style={{ flex: 1 }}>
<Container>
<Content padder>
<View>
<CurrencyWidget
currencyName={balancesMock.values.currencyBalances[0].name}
currencyCode={balancesMock.values.currencyBalances[0].code}
balance={balancesMock.values.currencyBalances[0].total}
inputAmount={buySourceAmount}
setInputAmount={(amount) => {
setBuySourceAmount(amount);
}}
autofocus
/>
<FeesSummary
feeAmount={feeAmount}
feeSubTotalAmount={feeSubTotalAmount}
/>
<RealTimeCryptoPriceWidget
currencyCode={balancesMock.values.cryptoBalances[0].code}
cryptoBuyPrice={cryptoBuyPrice}
/>
<CurrencyWidget
currencyName={balancesMock.values.cryptoBalances[0].name}
currencyCode={balancesMock.values.cryptoBalances[0].code}
balance={balancesMock.values.cryptoBalances[0].total}
inputAmount={buyDestinationAmount}
destinationCurrency
/>
</View>
<View>
<LoadingSpinner area="buy-button">
<Button
block
primary-light
style={{
marginBottom: 16,
}}
>
<Text>Buy {balancesMock.values.cryptoBalances[0].name}</Text>
</Button>
</LoadingSpinner>
</View>
</Content>
</Container>
</SafeAreaView>
);
};
const CurrencyWidget = (props) => {
console.log("Rendering CurrencyWidget");
return (
<Grid>
<Col>
<Text notification-light>
{props.currencyName} ({props.currencyCode})
</Text>
<Text label-light style={styles.balanceAmount}>
Balance: {props.currencyCode} {props.balance}
</Text>
</Col>
<Col style={{ alignItems: "flex-end", justifyContent: "flex-start" }}>
<Item regular>
<Input
transactionAmount
keyboardType="numeric"
placeholder="0"
editable={!props.destinationCurrency}
autoFocus={props.autofocus}
value={String(props.inputAmount)}
onChangeText={(amount) => {
console.log("amount: ", amount);
amount === ""
? props.setInputAmount("0")
: props.setInputAmount(amount);
}}
/>
</Item>
</Col>
</Grid>
);
};
const FeesSummary = props => {
const sellPageFees = () => {
return (
<Grid style={styles.verticalPadding}>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Subtotal</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>
EUR {props.feeSubTotalAmount}
</Text>
</Col>
</Row>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Fees</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>EUR {props.feeAmount}</Text>
</Col>
</Row>
</Grid>
);
};
const buyPageFees = () => {
return (
<Grid style={styles.verticalPadding}>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Fees</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>EUR {props.feeAmount}</Text>
</Col>
</Row>
<Row>
<Col style={styles.verticalCenter}>
<Text label-light>Subtotal</Text>
</Col>
<Col style={[styles.verticalCenter, { alignItems: "flex-end" }]}>
<Text notification-light-regular>
EUR {props.feeSubTotalAmount}
</Text>
</Col>
</Row>
</Grid>
);
};
console.log("Rendering FeeSummary");
return props.isSellPage ? sellPageFees() : buyPageFees();
};
<CurrencyWidget
currencyName={balancesMock.values.currencyBalances[0].name}
currencyCode={balancesMock.values.currencyBalances[0].code}
balance={balancesMock.values.currencyBalances[0].total}
inputAmount={buySourceAmount}
setInputAmount={handleBuySourceAmount}
autofocus
/>
您是否尝试过使用一种特殊的状态管理来了解它是如何工作的?类似于父级的onChange func来管理状态,而不是使用useffects,这样您就可以直接立即更改状态,而不是等待React来实现需要使用新数据重新呈现这些组件?编辑:您还可以考虑使用诸如from React之类的工具,并为这些组件创建自己的类似Redux的statemanager以及一个上下文。我想我已经通过您的建议实现了,谢谢!看到答案了吗