[英]Is it necessary to lift the state up when passing data to parent component?
我正在做我的 react native 項目,我認為我犯了一個大錯誤。 我有一個DaySelector
組件,它有一個Day
孩子。 他們的目的是創建一個多選欄,顯示一周中的每一天。 這是代碼:
import * as React from "react";
import { View, Text, StyleSheet, Button, Alert } from "react-native";
import { TouchableOpacity } from "react-native-gesture-handler";
import colors from "../assets/constants/style-variables";
interface Item {
selected: Boolean;
day: String;
}
function Day(props) {
return (
<TouchableOpacity
onPress={props.onPress}
style={props.selected ? styles.buttonActive : styles.button}
>
<Text>{props.day}</Text>
</TouchableOpacity>
);
}
export default class DaySelector extends React.Component<
{},
{ selectedItems: undefined | Item[]; items: Item[] }
> {
constructor(props) {
super(props);
this.state = {
selectedItems: [],
items: [
{
selected: false,
day: "Lu",
},
{
selected: false,
day: "Ma",
},
{
selected: false,
day: "Mi",
},
{
selected: false,
day: "Ju",
},
{
selected: false,
day: "Vi",
},
{
selected: false,
day: "Sa",
},
{
selected: false,
day: "Do",
},
],
};
}
onPress = (index) => {
let items = [...this.state.items];
let item = { ...items[index] };
item.selected = !item.selected;
items[index] = item;
this.setState({ items });
this.setState((prevState) => ({
selectedItems: prevState.items.filter((i) => i.selected),
}));
};
onCompleteSelection = () => {
console.log(this.state.selectedItems);
};
render() {
return (
<View>
<View style={styles.container}>
{this.state.items.map((item, index) => {
return (
<Day
key={index}
selected={item.selected}
day={item.day}
onPress={this.onPress.bind(this, index)}
/>
);
})}
</View>
<Button title={"Check"} onPress={this.onCompleteSelection} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: "row",
},
button: {
margin: 5,
borderColor: colors.lightGray,
borderWidth: 2,
borderRadius: 40,
padding: 7,
},
buttonActive: {
margin: 5,
borderColor: colors.primary,
borderWidth: 2,
backgroundColor: colors.primary,
borderRadius: 50,
padding: 7,
},
});
它工作得非常好,抓取數據並將其記錄在控制台中。 但問題是我將這個組件集成到另一個“表單”中,用戶不僅要選擇星期幾,還要選擇一些日程安排。 我需要放置一個“下一步”按鈕來匯總我所有組件抓取的數據。
我最大的是,我唯一能想到的就是將 state 抬起,這將非常復雜,因為父組件是一個功能組件:
import React, { useState } from "react";
import { useMutation } from "@apollo/react-hooks";
import { REGISTER } from "../Queries";
import Loader from "../components/Loader";
import DateTimePicker from "@react-native-community/datetimepicker";
import { View, Button, StyleSheet } from "react-native";
import colors from "../assets/constants/style-variables";
import { TouchableOpacity } from "react-native-gesture-handler";
import PrimaryText from "../assets/constants/PrimaryText";
import DaySelector from "../components/DaySelector";
export default function ScheduleSelect({ navigation, route }) {
const [loadingRegistration, setLoadingRegistration] = useState(null);
const [showTimePicker1, setShowTimePicker1] = useState(false);
const [showTimePicker2, setShowTimePicker2] = useState(false);
const [time1, setTime1] = useState(null);
const [time2, setTime2] = useState(null);
const show1 = () => {
setShowTimePicker1(true);
};
const show2 = () => {
setShowTimePicker2(true);
};
const handleTimePick1 = (event, selectedTime) => {
setShowTimePicker1(false);
if (selectedTime !== undefined) {
setTime1(selectedTime);
}
};
const handleTimePick2 = (event, selectedTime) => {
setShowTimePicker2(false);
if (selectedTime !== undefined) {
setTime2(selectedTime);
}
};
return (
<View style={styles.container}>
<PrimaryText fontSize={20} margin={22} textAlign={"center"}>
Recibirás turnos en estos horarios:
</PrimaryText>
<View style={styles.cardHolder}>
<View style={styles.card}>
<View style={styles.timeHelper}>
<PrimaryText textAlign={"center"}>Desde</PrimaryText>
</View>
{time1 && (
<TouchableOpacity onPress={show1}>
<View style={styles.timeSelected}>
<PrimaryText textAlign={"center"} fontSize={36}>
{`${time1?.getHours()}:${
time1.getMinutes() < 10
? "0" + time1.getMinutes()
: time1.getMinutes()
}`}
</PrimaryText>
</View>
</TouchableOpacity>
)}
{!time1 && (
<TouchableOpacity style={styles.button} onPress={show1}>
<PrimaryText fontSize={36} letterSpacing={2} textAlign={"center"}>
--:--
</PrimaryText>
</TouchableOpacity>
)}
{showTimePicker1 && (
<DateTimePicker
value={new Date()}
testID="dateTimePicker"
mode={"time"}
is24Hour={true}
display="default"
onChange={handleTimePick1}
/>
)}
</View>
<PrimaryText fontSize={36} margin={7}>
-
</PrimaryText>
<View style={styles.card}>
<View style={styles.timeHelper}>
<PrimaryText textAlign={"center"}>Hasta</PrimaryText>
</View>
{time2 && (
<TouchableOpacity onPress={show2}>
<View style={styles.timeSelected}>
<PrimaryText textAlign={"center"} fontSize={36}>
{`${time2?.getHours()}:${
time2.getMinutes() < 10
? "0" + time2.getMinutes()
: time2.getMinutes()
}`}
</PrimaryText>
</View>
</TouchableOpacity>
)}
{!time2 && (
<TouchableOpacity style={styles.button} onPress={show2}>
<PrimaryText fontSize={36} letterSpacing={2} textAlign={"center"}>
--:--
</PrimaryText>
</TouchableOpacity>
)}
{showTimePicker2 && (
<DateTimePicker
value={new Date()}
testID="dateTimePicker"
mode={"time"}
is24Hour={true}
display="default"
onChange={handleTimePick2}
/>
)}
</View>
</View>
{time2?.getTime() < time1?.getTime() && (
<PrimaryText color={colors.warning}>
Por favor, seleccioná horarios válidos
</PrimaryText>
)}
<PrimaryText margin={5}> Los días: </PrimaryText>
<View style={styles.card}>
<DaySelector />
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
width: "100%",
height: "100%",
justifyContent: "center",
alignItems: "center",
},
button: {
padding: 7,
},
card: {
flexDirection: "row",
justifyContent: "center",
backgroundColor: colors.iceWhite,
borderRadius: 10,
padding: 20,
marginBottom: 10,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
cardHolder: {
flexDirection: "row",
alignItems: "center",
},
timeHelper: {
justifyContent: "center",
position: "absolute",
marginTop: 5,
},
timeSelected: {
alignItems: "center",
justifyContent: "center",
},
editIcon: {
right: 3,
top: 3,
position: "absolute",
},
});
如您所見,它是一個非常大的組件,更糟糕的是,我必須將其設為 class 組件或嘗試將所有內容轉換為功能組件。 有什么辦法可以避免抬起 state 並將數據傳遞給父級?
只需創建一個回調 function 並將其傳遞給您的DaySelector
組件,以便您可以將值存儲在父 state
在你的父母
const handleChange = (value) => {
setDay(value);
}
<DaySelector onChange={handleChange} />
在你的孩子
onCompleteSelection = () => {
this.props.onChange(this.state.selectedItems);
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.