She*_*ixt 5 reactjs react-native redux react-redux
在我的 React Native 项目中,我在功能组件中使用 React Hooks 来设置我的 Redux 存储上的状态。然后我试图通过prop调用的方式将来自商店的值传递给子组件timestamp
问题是,子组件利用了DateTimePicker组件( from react-native-modal-datetime-picker),并且当它最初呈现timestampprop 时未定义,这会导致它出错。结果可以通过以下控制台日志看到:
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",
}
Run Code Online (Sandbox Code Playgroud)
组件被渲染两次。首先,道具是未定义的,然后它们被填充。
如何强制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;
Run Code Online (Sandbox Code Playgroud)
这是子组件:
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;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您有两种解决方案,这两种解决方案都取决于哪种解决方案更适合您或您的项目。
\n\n第一个解决方案是将start_date和设置end_date为有关报告的减速器的初始状态,但我不知道这对您的业务/规则是否有意义,不是最好的解决方案,但该解决方案“更简单”。
import React, { useEffect } from \'react\';\nimport { View } from \'react-native\';\nimport { useSelector, useDispatch } from \'react-redux\';\nimport DateInput from \'../../../components/DateTimeInput\';\nimport * as actions from \'../../../redux/actions\';\nimport moment from \'moment\';\n\nconst ReportParamsScreen = props => {\n const report = useSelector(state => state.report);\n const dispatch = useDispatch();\n\n useEffect(() => { \n dispatch(actions.setReportParams({ \n start_date : moment().subtract(30, "days"),\n end_date : moment()\n }))\n }, [dispatch]);\n\n if (!report.params.start_date) {\n return null\n }\n\n return (\n <View style={styles.row}>\n <View style={styles.column}>\n <DateInput \n mode="date"\n timestamp={report.params.start_date}\n />\n </View>\n <View style={styles.column}>\n <DateInput \n mode="date"\n timestamp={report.params.start_date}\n />\n </View>\n </View>\n )\n};\n\nexport default ReportParamsScreen;\nRun Code Online (Sandbox Code Playgroud)\n\n第二种解决方案是验证report.params.start_date上是否未定义ReportParamsScreen,如果为 true,则在日期为 null 时在组件上返回 null 或返回表示 like 的组件Loading,是一个很好的做法。
例子:
\n\nimport React, { useEffect } from \'react\';\nimport { View } from \'react-native\';\nimport { useSelector, useDispatch } from \'react-redux\';\nimport DateInput from \'../../../components/DateTimeInput\';\nimport * as actions from \'../../../redux/actions\';\nimport moment from \'moment\';\n\nconst ReportParamsScreen = props => {\n const report = useSelector(state => state.report);\n const dispatch = useDispatch();\n\n useEffect(() => { \n dispatch(actions.setReportParams({ \n start_date : moment().subtract(30, "days"),\n end_date : moment()\n }))\n }, [dispatch]);\n\n if (!report.params.start_date) {\n return <Loading />\n }\n\n return (\n <View style={styles.row}>\n <View style={styles.column}>\n <DateInput \n mode="date"\n timestamp={report.params.start_date}\n />\n </View>\n <View style={styles.column}>\n <DateInput \n mode="date"\n timestamp={report.params.start_date}\n />\n </View>\n </View>\n )\n};\n\nexport default ReportParamsScreen;\nRun Code Online (Sandbox Code Playgroud)\n\n这种情况曾经发生过,因为useEffect只在渲染后执行。
参考:
\n\n\n\n\nuseEffect 有什么作用?通过使用这个 Hook,您可以告诉 React 您的组件需要在渲染后执行某些操作。React 会记住您传递的函数(我们将其称为 \xe2\x80\x9ceffect\xe2\x80\x9d),并在执行 DOM 更新后调用它。在这种效果中,我们设置了文档标题,但我们也可以执行数据获取或调用其他命令式 API。
\n
链接: https: //reactjs.org/docs/hooks-effect.html
\n| 归档时间: |
|
| 查看次数: |
4934 次 |
| 最近记录: |