【发布时间】:2021-03-04 13:56:23
【问题描述】:
我目前正在使用 react native 开发应用程序,但遇到了一个特定问题。我的应用程序有 3 个主屏幕。一是在存储在设备上的列表中简要显示数据,二是从用户输入新数据并存储,三是显示数据但更详细。所有这些屏幕都包含在我的 app.js 文件中,其中我有我的 NavigationContainer。在我的主屏幕组件(简要显示数据的组件)中,我有一个名为 list 的状态对象,我在其中加载用户保存的所有输入。当用户点击一个按钮时,他被带到上述输入屏幕。在这里,我有滑块,用户可以在其中设置他/她想要的输入,还有一个按钮来保存输入。当点击保存按钮时,数据应该被保存,用户被带回主屏幕,并且用户应该看到他/她所做的输入。
现在到我试图提出的尝试解决方案。我尝试将输入作为 navigation.navigate() 方法的对象参数传入。在主屏幕组件上,我试图在 useEffect() 钩子中捕获对象,但首先检查它是否未定义(因为它是主屏幕,我不应该在用户打开时在开头添加一个空对象应用程序)。我也尝试更新列表对象的状态,但它不起作用。应用程序崩溃,日志中未显示任何错误。此外,我无法将输入保存到输入组件中的设备,因为我需要将它们添加到先前保存的列表的其余部分,然后保存该新列表。我想在输入屏幕类中使列表对象成为状态对象,但我需要主屏幕的列表,因为我在那里显示所有数据。我也无法将按钮的 onPress 事件向上传递,因为它们是不相关的组件。我也不能将状态放在 app.js 类中,因为从我收集到的信息中,我不能将函数作为道具传递给堆栈导航器的屏幕组件。通过研究这个问题,我发现使用 redux 可以成为更新任何组件状态的解决方案。但是,我认为这种解决方案有点矫枉过正,因为我只需要处理一个状态对象,而且我没有很多组件使用它。
最好的方法是什么?我使用 useEffect 钩子错了吗?我应该使用其他挂钩来更新列表吗?如何更新值,然后设置屏幕导航到的状态?
代码:
function PreviousTasksScreen(props) {
prevList = [];
const [list, setList] = useState(prevList);
getCurrentDate = () => {
var date = new Date().getDate();
var month = new Date().getMonth() + 1;
var year = new Date().getFullYear();
return date + "-" + month + "-" + year; //format: dd-mm-yyyy;
};
getTotalRating = (ratingList) => {
let total = ratingList.reduce(function (prev, cur) {
return prev + cur.value;
}, 0);
return total;
/*ratingList.array.forEach(element => {
element.value
});*/
};
/*const save = async () => {
try {
await AsyncStorage.setItem("List", prevList);
} catch (err) {
alert(err);
}
};
const load = async () => {
try {
let list = await AsyncStorage.getItem("List");
if (list !== null) {
setList(list);
}
} catch (err) {
alert(err);
}
};*/
useEffect(() => {
if (typeof props.route.params !== "undefined") {
console.log("has the parent");
if (typeof props.route.params.otherParam !== "undefined") {
let par = props.route.params.otherParam;
console.log("has the object");
prevList = [...list];
prevList.push(par);
//console.log(prevList);
//setList(prevList);
//save();
//console.log(list);
}
} else {
//load();
console.log("prarameter is undefined");
}
//load();
console.log("useEffect called");
setList(prevList);
});
return (
<SafeAreaView style={styles.container}>
<Button
title="Add Review"
onPress={() => props.navigation.navigate("addReview")}
></Button>
<FlatList
data={list}
renderItem={({ item }) => (
<ListItem
date={item.date}
rating={item.totalRating}
id={item.key}
nav={props.navigation}
/>
)}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
justifyContent: "center",
},
item: {
width: "100%",
height: 70,
},
title: {
fontSize: 20,
left: 20,
},
});
export default PreviousTasksScreen;
对于输入屏幕:
class ReviewTasksScreen extends Component {
state = {
myList: [
{ id: 1, title: "test1", value: 3 },
{ id: 2, title: "test2", value: 5 },
{ id: 3, title: "test3", value: 2 },
],
//prevReviewLists: [],
};
constructor() {
super();
console.log("App-Constructor");
}
/*printList = () => {
console.log(list);
};*/
handleCallback = (reviewItem) => {
const myList = [...this.state.myList];
const index = myList.indexOf(reviewItem);
myList[index] = { ...reviewItem };
this.setState({ myList });
//setList({ lst });
};
deleteExtra = (rItem) => {
delete rItem.title;
};
addToList = () => {
const saveList = this.state.myList.map(({ id, value }) => ({ id, value }));
//console.log(saveList);
let myObject = {
date: "",
key: 1,
myList: "",
totalRating: 0,
};
myObject.date = getCurrentDate();
myObject.totalRating = getTotalRating(saveList);
myObject.myList = saveList;
console.log(myObject);
this.props.navigation.navigate("list", {
otherParam: myObject,
});
};
render() {
return (
<ScrollView>
{this.state.myList.map((item) => (
<ReviewItem
key={item.id}
id={item.id}
title={item.title}
value={item.value}
item={item}
handleChange={this.handleCallback}
/>
))}
<Button title="Save" onPress={this.addToList}></Button>
</ScrollView>
);
}
}
export default ReviewTasksScreen;
【问题讨论】:
-
你最好使用redux来达到这个目的。
-
在此处分享您的代码。没有人会读你的故事。
-
我已经添加了代码。我认为这是一个我没有看到的简单逻辑错误,这就是我最初没有包含代码的原因。我还尝试提供尽可能多的背景信息,并希望展示我尝试解决问题的所有不同方式,抱歉问题太长了。
标签: javascript reactjs react-native