React Hooks+Redux技术问题:生命周期选择、表单初始化与渲染次数
Hey there, let's break down your questions one by one and fix the issues in your code along the way!
React Hooks don’t rely on the old class-based lifecycle methods like componentDidMount or componentDidUpdate. Instead, we use useEffect to replicate their behavior, paired with useSelector to react to changes in your Redux store.
Here’s how to map common lifecycle needs to Hooks:
- Run code once on mount (like fetching initial user data): Use
useEffectwith an empty dependency array. This ensures it only runs after the first render.useEffect(() => { props.dispatch(fetchUser(props.match.params.id)); }, []); - React to Redux state changes (like when the
userdata finishes loading): Add theuservalue fromuseSelectorto theuseEffectdependency array. This will re-run the effect wheneveruserupdates. - Cleanup tasks (like canceling API requests): Return a cleanup function from
useEffect— this runs when the component unmounts or before the effect re-runs.
The problem in your code is that useState only uses its initial value once, when the component first renders. At that point, your Redux user is likely still empty (since data loading is asynchronous). So your formData gets initialized with empty values and never updates when the user actually loads.
Here’s the fix: use useEffect to sync formData with the Redux user whenever it changes:
const EditUser = (props) => { const user = useSelector(state => state.user); // Start with empty form values (or sensible defaults) const [formData, setFormData] = useState({ email: '', fullName: '', image: null }); // Update formData when the user data loads/updates useEffect(() => { if (Object.keys(user).length > 0) { setFormData(prev => ({ ...prev, // Keep any existing changes the user made (like a selected image) email: user.email, fullName: user.fullName })); } }, [user]); // Re-run this effect whenever user changes // ... rest of your handleSubmit, handleChange, fileHandle functions }
This way, as soon as the user data is available in the Redux store, your form will populate with the correct initial values. We use the prev state in setFormData to preserve any changes the user might have made before the user finished loading (like selecting an image early).
This is usually a combination of a few factors, especially in development:
- Initial render: The component mounts for the first time.
- Redux state update: When the
userdata finishes loading from the store,useSelectordetects the change and triggers a re-render. - Form state update: After the
userloads, theuseEffectwe added updatesformData, which triggers another re-render. - React Strict Mode: If your app is wrapped in
<StrictMode>(default in Create React App), React intentionally double-renders components in development to catch accidental side effects. This means each of the above renders happens twice, adding up to 4 total.
To confirm if Strict Mode is the cause, check your root index.js file — if you see <React.StrictMode>, removing it will cut the render count in half. That said, keeping Strict Mode is recommended for development, as it helps catch bugs early.
内容的提问来源于stack exchange,提问作者Harishbn

