React Native实现为派对对象单独添加用户的方法
解决方案:给已有派对添加用户
核心思路
要实现独立添加用户到指定派对的功能,需要新增选中派对的状态管理,并编写专门的添加用户逻辑,而非仅在创建派对时初始化用户列表。
具体修改步骤
1. 新增状态变量
在组件顶部添加状态,用于记录当前选中的派对ID:
const [selectedPartyId, setSelectedPartyId] = useState(null);
2. 编写添加用户的处理函数
创建handleAddUser函数,根据选中的派对ID,将新用户追加到对应派对的users数组中:
const handleAddUser = () => { if (!selectedPartyId || !userName.trim()) return; setParties(prevParties => prevParties.map(party => { if (party.id === selectedPartyId) { // 生成唯一用户ID,用当前用户列表最大ID+1保证唯一性 const newUserId = party.users.length > 0 ? Math.max(...party.users.map(u => u.id)) + 1 : 0; return { ...party, users: [...party.users, { id: newUserId, name: userName }] }; } return party; }) ); setUser(""); // 清空输入框 };
3. 调整UI,添加选中和添加用户的交互
调整派对项的渲染
给每个派对项添加选中样式,并绑定选中事件:
{parties.map((item, index) => { const isSelected = item.id === selectedPartyId; return ( <TouchableOpacity key={index} onPress={() => setSelectedPartyId(item.id)} style={[styles.partyItem, isSelected && styles.selectedParty]} > <Task name={item.partyName} description={item.description} date={item.date}></Task> <Text style={styles.userListTitle}>参与用户:</Text> {item.users.map((user, userIndex) => ( <View key={userIndex} style={styles.userItem}> <Text>{user.name}</Text> </View> ))} </TouchableOpacity> ); })}
新增添加用户的专属区域
在页面底部添加用于给选中派对加用户的输入框和按钮:
{selectedPartyId && ( <View style={styles.addUserSection}> <TextInput style={[styles.input, styles.userInput]} placeholder="输入要添加的用户名" value={userName} onChangeText={setUser} /> <TouchableOpacity onPress={handleAddUser} style={styles.addWrapper}> <Text style={styles.addText}>添加用户</Text> </TouchableOpacity> </View> )}
4. 补充样式(提升交互体验)
添加选中派对和用户列表的样式:
const styles = StyleSheet.create({ // 原有样式保留,新增以下样式 partyItem: { marginBottom: 15, padding: 15, borderWidth: 1, borderColor: '#eee', borderRadius: 8, backgroundColor: '#fff', }, selectedParty: { borderColor: '#2196F3', backgroundColor: '#E3F2FD', }, userListTitle: { fontSize: 16, fontWeight: '600', marginTop: 10, marginBottom: 5, }, userItem: { fontSize: 14, paddingVertical: 2, paddingLeft: 10, }, addUserSection: { position: 'absolute', bottom: 10, width: '100%', flexDirection: 'row', justifyContent: 'space-around', alignItems: 'center', paddingHorizontal: 10, }, userInput: { flex: 1, marginBottom: 0, }, });
5. 优化创建派对逻辑(可选)
如果希望创建派对时可以不填初始用户,修改handleAddButtonClick中的用户初始化部分:
users: userName.trim() ? [{ id: 0, name: userName }] : []
完整修改后的代码
import React, { useState } from "react"; import { Platform, KeyboardAvoidingView, StyleSheet, Text, View, TextInput, TouchableOpacity, ScrollView, } from "react-native"; import Task from "./components/task"; export default function App() { const [partyTitle, setPartyName] = useState(""); const [description, setDescription] = useState(""); const [date, setDate] = useState(""); const [userName, setUser] = useState(""); const [selectedPartyId, setSelectedPartyId] = useState(null); const [parties, setParties] = useState([ { partyName: "Party 1", description: "test", id: 0, date:"12.01.2022", users:[{id:0, name:'John'}] }, ]); const handleAddButtonClick = () => { if (!partyTitle.trim()) return; setParties((prev) => [ ...prev, { partyName: partyTitle, description: description, id: prev.length, // 用prev.length保证ID唯一 date: date, users: userName.trim() ? [{ id: 0, name: userName }] : [] }, ]); setPartyName(""); setDescription(""); setDate(""); setUser(""); }; const handleAddUser = () => { if (!selectedPartyId || !userName.trim()) return; setParties(prevParties => prevParties.map(party => { if (party.id === selectedPartyId) { const newUserId = party.users.length > 0 ? Math.max(...party.users.map(u => u.id)) + 1 : 0; return { ...party, users: [...party.users, { id: newUserId, name: userName }] }; } return party; }) ); setUser(""); }; return ( <View style={styles.container}> <ScrollView contentContainerStyle={{ flexGrow: 1 }} keyboardShouldPersistTaps="handled" > <View style={styles.tasksWrapper}> <Text style={styles.sectionTitle}>Upcoming parties</Text> <View style={styles.items}> {parties.map((item, index) => { const isSelected = item.id === selectedPartyId; return ( <TouchableOpacity key={index} onPress={() => setSelectedPartyId(item.id)} style={[styles.partyItem, isSelected && styles.selectedParty]} > <Task name={item.partyName} description={item.description} date={item.date}></Task> <Text style={styles.userListTitle}>参与用户:</Text> {item.users.map((user, userIndex) => ( <View key={userIndex} style={styles.userItem}> <Text>{user.name}</Text> </View> ))} </TouchableOpacity> ); })} </View> </View> </ScrollView> <KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : "height"} style={styles.writeTaskWrapper} > <View style={styles.createPartySection}> <TextInput style={styles.input} placeholder="输入派对名称" value={partyTitle} onChangeText={setPartyName} /> <TextInput style={styles.input} placeholder="输入派对描述" value={description} onChangeText={setDescription} /> <TextInput style={styles.input} placeholder="输入派对日期" value={date} onChangeText={setDate} /> <TextInput style={styles.input} placeholder="初始用户(可选)" value={userName} onChangeText={setUser} /> </View> <TouchableOpacity onPress={handleAddButtonClick}> <View style={styles.addWrapper}> <Text style={styles.addText}>创建派对</Text> </View> </TouchableOpacity> </KeyboardAvoidingView> {/* 添加用户区域 */} {selectedPartyId && ( <View style={styles.addUserSection}> <TextInput style={[styles.input, styles.userInput]} placeholder="输入要添加的用户名" value={userName} onChangeText={setUser} /> <TouchableOpacity onPress={handleAddUser} style={styles.addWrapper}> <Text style={styles.addText}>添加用户</Text> </TouchableOpacity> </View> )} </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#E8EAED', }, tasksWrapper: { paddingTop: 80, paddingHorizontal: 20, }, sectionTitle: { fontSize: 24, fontWeight: 'bold', }, items: { marginTop: 30, }, writeTaskWrapper: { position: 'absolute', bottom: 60, width: '100%', flexDirection: 'row', justifyContent: 'space-around', alignItems: 'center', }, createPartySection: { flexDirection: 'column', flex: 1, paddingHorizontal: 10, }, input: { paddingVertical: 15, paddingHorizontal: 15, backgroundColor: '#FFF', borderRadius: 60, borderColor: '#C0C0C0', borderWidth: 1, width: '100%', marginBottom: 10, }, addWrapper: { width: 60, height: 60, backgroundColor: '#FFF', borderRadius: 60, justifyContent: 'center', alignItems: 'center', borderColor: '#C0C0C0', borderWidth: 1, marginRight: 10, }, addText: {}, // 新增样式 partyItem: { marginBottom: 15, padding: 15, borderWidth: 1, borderColor: '#eee', borderRadius: 8, backgroundColor: '#fff', }, selectedParty: { borderColor: '#2196F3', backgroundColor: '#E3F2FD', }, userListTitle: { fontSize: 16, fontWeight: '600', marginTop: 10, marginBottom: 5, }, userItem: { fontSize: 14, paddingVertical: 2, paddingLeft: 10, }, addUserSection: { position: 'absolute', bottom: 10, width: '100%', flexDirection: 'row', justifyContent: 'space-around', alignItems: 'center', paddingHorizontal: 10, }, userInput: { flex: 1, marginBottom: 0, }, });
关键说明
- 选中派对:点击任意派对即可选中,选中后会显示高亮样式,此时输入用户名并点击「添加用户」即可将用户加入该派对
- 用户ID唯一性:通过取当前派对用户ID的最大值加1来生成新ID,避免重复
- 输入校验:创建派对时必须填写名称,添加用户时必须选中派对且输入用户名,避免无效操作
内容的提问来源于stack exchange,提问作者User G Amsterdam
相关产品推荐
相关产品推荐

