如何正确使用HOC与recompose?React新手的可编辑容器实现疑问
Fixing Your Editable Row HOC with Recompose
Hey there! Since you're new to React and working on an editable container using a Higher-Order Component (HOC) with Recompose, let's sort out that editableRow HOC and get it working properly.
First, Let's Refine the HOC Code
Here's a corrected and complete version of your editableRow HOC with proper state handling and additional helpers for save/cancel actions:
import React from 'react'; import { withStateHandlers, withHandlers, compose } from 'recompose'; const editableRow = () => compose( // Manage editing state withStateHandlers( { isEditing: false, editingId: null }, { toggleEditing: ({ isEditing, editingId }) => (entryId) => ({ // Toggle editing state: if already editing, turn it off and clear editingId isEditing: !isEditing, // Only set editingId if we're turning editing ON editingId: !isEditing ? entryId : null }), // Helper to force exit editing state (useful for cancel/save) exitEditing: () => () => ({ isEditing: false, editingId: null }) } ), // Add handlers for save/cancel actions withHandlers({ handleSave: ({ exitEditing }) => (saveCallback, entryData) => { // Execute the parent-provided save logic if (typeof saveCallback === 'function') { saveCallback(entryData); } // Exit editing state after save exitEditing(); }, handleCancel: ({ exitEditing }) => () => { // Just exit editing without saving exitEditing(); } }) ); export default editableRow;
How to Use This HOC
Now wrap your row component with this HOC, and use the injected props to toggle between view and edit modes:
// Example Row component that will be wrapped const Row = ({ entry, isEditing, editingId, toggleEditing, handleSave, handleCancel }) => { const isCurrentEntryEditing = isEditing && editingId === entry.id; if (isCurrentEntryEditing) { // Render edit form when in editing mode return ( <div className="editable-row"> <input type="text" defaultValue={entry.name} ref={(input) => { if (input) input.focus(); }} /> <button onClick={() => handleSave( (data) => console.log('Saving:', data), { ...entry, name: event.target.previousSibling.value } )}> Save </button> <button onClick={handleCancel}>Cancel</button> </div> ); } // Render view mode when not editing return ( <div className="row"> <span>{entry.name}</span> <button onClick={() => toggleEditing(entry.id)}>Edit</button> </div> ); }; // Wrap the Row component with our HOC const EditableRow = editableRow()(Row); // Use EditableRow in your parent component const DataTable = ({ entries }) => ( <div> {entries.map(entry => ( <EditableRow key={entry.id} entry={entry} /> ))} </div> );
Key Fixes & Explanations
- Corrected
toggleEditingLogic: The original code had an incomplete assignment foreditingId— now we only set it when enabling editing, and clear it when disabling. - Added
exitEditingHelper: A dedicated function to safely exit editing mode, which is reused in save/cancel handlers to avoid code duplication. - Explicit Save/Cancel Handlers: These make it easy to integrate with parent component logic (like API calls) while keeping the HOC reusable.
- Clear Prop Usage: The wrapped
Rowcomponent checks if the current entry's ID matcheseditingIdto ensure only the clicked row enters edit mode.
Quick Notes
- Make sure your Recompose version is up to date (though the core functions used here are stable).
- If you're moving to modern React, keep in mind that Recompose patterns can be replaced with custom hooks, but since you're working with HOCs right now, this approach is solid.
内容的提问来源于stack exchange,提问作者Istvan Orban
相关产品推荐
相关产品推荐

