嵌套组件状态更新的正确方式——React技术栈Reddit克隆开发问询
Hey there! Let's walk through the right way to build that edit post feature—where clicking an edit link navigates to the edit route and auto-populates the form fields—using your tech stack. Based on what you described, here's a step-by-step breakdown with tailored code examples:
1. Refine Your Container Component Logic
First, let's fix up your PostContainer to fetch the right post data when the component mounts and when the route parameters change (since navigating to a different edit URL won't remount the component, just update its props). We'll use react-redux's connect to link Redux state to component props, and handle data fetching in both lifecycle methods:
import { connect } from 'react-redux'; import { fetchSinglePost } from '../actions/postActions'; // Your action to fetch a single post import PostEditForm from '../components/PostEditForm'; class PostContainer extends Component { componentDidMount() { this.loadPostData(); } componentDidUpdate(prevProps) { // Re-fetch if the post ID in the route has changed if (prevProps.match.params.id !== this.props.match.params.id) { this.loadPostData(); } } loadPostData = () => { const postId = this.props.match.params.id; this.props.fetchSinglePost(postId); // Dispatch the fetch action }; render() { const { currentPost, isLoading } = this.props; if (isLoading) return <div>Loading post...</div>; if (!currentPost) return <div>Post not found!</div>; // Pass the fetched post data to the edit form return <PostEditForm post={currentPost} />; } } // Map Redux store state to component props const mapStateToProps = (state) => ({ currentPost: state.posts.selectedPost, // Adjust to match your store structure isLoading: state.posts.isLoading }); // Map dispatch actions to props const mapDispatchToProps = { fetchSinglePost }; export default connect(mapStateToProps, mapDispatchToProps)(PostContainer);
2. Build the Edit Form with State Sync
Your nested PostEditForm needs to take the post prop and initialize its local state with the post's data. For class components, we'll use getDerivedStateFromProps to update the state if the post prop changes (like when the user navigates to edit a different post):
import React, { Component } from 'react'; import { updatePost } from '../actions/postActions'; // Your action to save post changes import { connect } from 'react-redux'; class PostEditForm extends Component { state = { postId: '', title: '', content: '' }; // Sync state with incoming post prop static getDerivedStateFromProps(nextProps, prevState) { const incomingPost = nextProps.post; if (incomingPost && incomingPost.id !== prevState.postId) { return { postId: incomingPost.id, title: incomingPost.title, content: incomingPost.content }; } return null; } handleInputChange = (e) => { const { name, value } = e.target; this.setState({ [name]: value }); }; handleSubmit = (e) => { e.preventDefault(); const { postId, title, content } = this.state; this.props.updatePost(postId, { title, content }); // Navigate back to the post page after saving this.props.history.push(`/posts/${postId}`); }; render() { const { title, content } = this.state; return ( <form onSubmit={this.handleSubmit} className="post-edit-form"> <div className="form-group"> <label>Post Title:</label> <input type="text" name="title" value={title} onChange={this.handleInputChange} required /> </div> <div className="form-group"> <label>Post Content:</label> <textarea name="content" value={content} onChange={this.handleInputChange} rows="8" required /> </div> <button type="submit" className="save-btn">Save Changes</button> </form> ); } } const mapDispatchToProps = { updatePost }; export default connect(null, mapDispatchToProps)(PostEditForm);
3. Key Tips to Avoid Pitfalls
- Route Parameter Changes: Don't only rely on
componentDidMount—usecomponentDidUpdateto detect when theidinmatch.paramschanges, so you fetch the correct post data. - Controlled Components: Tie form fields to the component's local state for real-time input handling, while keeping the initial values synced with the Redux-fetched post data.
- Redux Store Updates: Ensure your
fetchSinglePostaction correctly updates the Redux store with the selected post, so the container receives the updated prop and passes it to the form. - Lifecycle Best Practices: Use
getDerivedStateFromProps(instead of deprecated methods likecomponentWillReceiveProps) to sync state with prop changes in class components.
4. Quick Route Setup Reminder
Make sure your React Router v4 routes are configured to render the PostContainer for edit URLs:
import { Route } from 'react-router-dom'; import PostContainer from './containers/PostContainer'; // In your app's route configuration <Route path="/posts/:id/edit" component={PostContainer} />
That should get your edit form auto-populating perfectly when navigating to the route. Let me know if you need to tweak any part for your specific store structure!
内容的提问来源于stack exchange,提问作者HelloWorld

