如何实现Touchable组件按压样式切换,多组件仅一个可选中(非Redux)
Got it, let's solve this problem without Redux—we can handle the active state centrally in the parent App component since it's the one rendering all ActivityButton instances. This approach keeps things simple, avoids redundant local state in child components, and ensures only one button is active at a time.
Step 1: Update the App Component
First, we'll add a state variable to track the currently active button, plus a handler to update this state when a button is pressed. We'll also pass each button its active status and press handler via props.
class App extends React.Component { constructor(props) { super(props); // Track the ID/title of the currently active button (null = no active button) this.state = { activeButtonId: null }; } // Handler to update active state AND run your original submit logic handleButtonPress = (buttonId) => { // Set the pressed button as the active one this.setState({ activeButtonId: buttonId }); // Execute your existing submit logic for the button this.submitHandler(buttonId); }; submitHandler = (buttonId) => { // Your existing business logic here (e.g., API calls, form submissions) console.log(`Processing action for button: ${buttonId}`); }; render() { return ( <View> <ActivityButton activityTitle={"B1"} // Pass whether this button is currently active isActive={this.state.activeButtonId === "B1"} // Pass the centralized press handler onPress={() => this.handleButtonPress("B1")} /> <ActivityButton activityTitle={"B2"} isActive={this.state.activeButtonId === "B2"} onPress={() => this.handleButtonPress("B2")} /> </View> ); } }
Step 2: Simplify the ActivityButton Component
Now the child component no longer needs to manage its own active state—it just uses the isActive prop from the parent to determine its style. This makes the component fully reusable across your app without any state tied to activation.
class ActivityButton extends React.Component { render() { const { activityTitle, isActive, onPress } = this.props; return ( <TouchableOpacity style={isActive ? styles.buttonPress : styles.button} onPress={onPress} > <View> <Text>{activityTitle}</Text> </View> </TouchableOpacity> ); } } // Example styles (tweak these to match your app's design) const styles = StyleSheet.create({ button: { padding: 12, backgroundColor: '#f0f0f0', borderRadius: 6, marginVertical: 8, alignItems: 'center' }, buttonPress: { padding: 12, backgroundColor: '#2196f3', borderRadius: 6, marginVertical: 8, alignItems: 'center', // Add subtle press feedback (e.g., slight scale down) transform: [{ scale: 0.97 }] } });
Key Benefits of This Approach
- Single Source of Truth: All button activation state lives in the parent, guaranteeing only one button is active at any time.
- Fully Reusable: The
ActivityButtoncomponent can be dropped anywhere in your app—just passisActiveandonPressprops, no local state setup needed. - No Redux Required: We're using React's native parent-child prop flow, which is perfect for this localized state scenario.
Optional: Add Toggle Behavior
If you want clicking an already active button to deactivate it, adjust the handleButtonPress function like this:
handleButtonPress = (buttonId) => { this.setState(prevState => ({ activeButtonId: prevState.activeButtonId === buttonId ? null : buttonId })); this.submitHandler(buttonId); };
Optional: Use Unique IDs (Instead of Titles)
If your button titles might not be unique, add a uniqueId prop for safer state tracking:
// In App component's render <ActivityButton uniqueId="btn-task-1" activityTitle={"B1"} isActive={this.state.activeButtonId === "btn-task-1"} onPress={() => this.handleButtonPress("btn-task-1")} />
内容的提问来源于stack exchange,提问作者RVieira

