gpt4 book ai didi

reactjs - 如何使用 React Hooks 在第一次渲染时加载带有 props 的子组件

转载 作者:行者123 更新时间:2023-12-03 13:44:59 25 4
gpt4 key购买 nike

在我的 React Native 项目中,我在功能组件中使用 React Hooks 来设置 Redux 存储上的状态。然后,我尝试通过名为 timestamp

prop 将存储中的值传递到子组件中

问题是,子组件利用了 DateTimePicker 组件(来自 react-native-modal-datetime-picker),并且当它最初渲染 >timestamp 属性未定义,这会导致错误。通过以下控制台日志可以看到结果:

undefined
undefined
Object {
"date": "2019-08-20",
"full": 2019-08-20T12:21:52.874Z,
"time": "01:21:52",
}
Object {
"date": "20.08.2019",
"time": "01:21 pm",
}

该组件被渲染两次。首先, Prop 是未定义的,然后它们会被填充。

如何强制在第一次渲染之前加载 props

我不想直接在子组件中调用状态,因为这将被重用于各种用例。

这是父组件:

import React, { useEffect } from 'react';
import { View } from 'react-native';
import { useSelector, useDispatch } from 'react-redux';
import DateInput from '../../../components/DateTimeInput';
import * as actions from '../../../redux/actions';
import moment from 'moment';

const ReportParamsScreen = props => {
const report = useSelector(state => state.report);
const dispatch = useDispatch();

useEffect(() => {
dispatch(actions.setReportParams({
start_date : moment().subtract(30, "days"),
end_date : moment()
}))
}, [dispatch]);

return (
<View style={styles.row}>
<View style={styles.column}>
<DateInput
mode="date"
timestamp={report.params.start_date}
/>
</View>
<View style={styles.column}>
<DateInput
mode="date"
timestamp={report.params.start_date}
/>
</View>
</View>
)
};

export default ReportParamsScreen;

这是子组件:

import React, { useEffect, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Body, Button, Text, Icon } from "native-base";
import DateTimePicker from "react-native-modal-datetime-picker";

const DateInput = props => {
const [isPickerVisible, setIsPickerVisible] = useState(false);

const showDateTimePicker = () => {
setIsPickerVisible(true);
};

const hideDateTimePicker = () => {
setIsPickerVisible(false);
};

const handleDateTimePicked = dateTime => {
console.log(dateTime)
hideDateTimePicker();
};

console.log(props.timestamp.value);
console.log(props.timestamp.labels); // These are the logs referened above.

return (
<Body>
<Button transparent onPress={showDateTimePicker}>
<Icon
type="MaterialIcons"
name={props.mode == 'time' ? 'access-time' : 'date-range' }
/>
<Text>{props.timestamp.labels[props.mode]}</Text>
</Button>
<DateTimePicker
date={props.timestamp.value.date}
mode={props.mode}
isVisible={isPickerVisible}
onConfirm={handleDateTimePicked}
onCancel={hideDateTimePicker}
/>
</Body>
);
}

export default DateInput;

最佳答案

在这种情况下,您有两种解决方案,这两种解决方案都取决于哪种解决方案更适合您或您的项目。

第一个解决方案是将 start_dateend_date 设置为有关报告的 reducer 的初始状态,但我不知道这对您的业务/规则是否有意义,是这不是最好的解决方案,但该解决方案“更简单”。

import React, { useEffect } from 'react';
import { View } from 'react-native';
import { useSelector, useDispatch } from 'react-redux';
import DateInput from '../../../components/DateTimeInput';
import * as actions from '../../../redux/actions';
import moment from 'moment';

const ReportParamsScreen = props => {
const report = useSelector(state => state.report);
const dispatch = useDispatch();

useEffect(() => {
dispatch(actions.setReportParams({
start_date : moment().subtract(30, "days"),
end_date : moment()
}))
}, [dispatch]);

if (!report.params.start_date) {
return null
}

return (
<View style={styles.row}>
<View style={styles.column}>
<DateInput
mode="date"
timestamp={report.params.start_date}
/>
</View>
<View style={styles.column}>
<DateInput
mode="date"
timestamp={report.params.start_date}
/>
</View>
</View>
)
};

export default ReportParamsScreen;

第二个解决方案是验证 report.params.start_dateReportParamsScreen 上未定义,如果为 true,则在日期为 null 时在组件上返回 null 或返回像Loading这样表示的组件是一个很好的实践。

示例:

import React, { useEffect } from 'react';
import { View } from 'react-native';
import { useSelector, useDispatch } from 'react-redux';
import DateInput from '../../../components/DateTimeInput';
import * as actions from '../../../redux/actions';
import moment from 'moment';

const ReportParamsScreen = props => {
const report = useSelector(state => state.report);
const dispatch = useDispatch();

useEffect(() => {
dispatch(actions.setReportParams({
start_date : moment().subtract(30, "days"),
end_date : moment()
}))
}, [dispatch]);

if (!report.params.start_date) {
return <Loading />
}

return (
<View style={styles.row}>
<View style={styles.column}>
<DateInput
mode="date"
timestamp={report.params.start_date}
/>
</View>
<View style={styles.column}>
<DateInput
mode="date"
timestamp={report.params.start_date}
/>
</View>
</View>
)
};

export default ReportParamsScreen;

这种情况曾经发生过,因为 useEffect 仅在渲染后执行。

引用:

What does useEffect do? By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we’ll refer to it as our “effect”), and call it later after performing the DOM updates. In this effect, we set the document title, but we could also perform data fetching or call some other imperative API.

链接:https://reactjs.org/docs/hooks-effect.html

关于reactjs - 如何使用 React Hooks 在第一次渲染时加载带有 props 的子组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58011056/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com