如何将子组件函数传递给父组件?多TextBox对应Toolbar场景
Got it, let's break down how to solve this problem. The core issue is making sure each Toolbar can control its corresponding TextBox—since you're rendering dynamic numbers of these components, we'll use unique identifiers and let the parent App component handle state and communication between pairs.
Step 1: Refactor App State to Track Each TextBox
First, update your App component's state to store an array of objects, where each object represents a TextBox with a unique ID and its content. This lets us track each text box individually.
class App extends React.Component { constructor(props) { super(props); this.state = { // Initialize with one text box; users can add more later textBoxes: [{ id: Date.now(), content: '' }] }; } // Add a new TextBox-Toolbar pair addTextBox = () => { this.setState(prevState => ({ textBoxes: [...prevState.textBoxes, { id: Date.now(), content: '' }] })); }; // Update content for a specific TextBox updateTextBoxContent = (textBoxId, newContent) => { this.setState(prevState => ({ textBoxes: prevState.textBoxes.map(textBox => textBox.id === textBoxId ? { ...textBox, content: newContent } : textBox ) })); }; // Optional: Remove a TextBox-Toolbar pair removeTextBox = (textBoxId) => { this.setState(prevState => ({ textBoxes: prevState.textBoxes.filter(textBox => textBox.id !== textBoxId) })); }; render() { return ( <div className="app-container"> {/* Button to add new pairs */} <button onClick={this.addTextBox}>Add New Text Box</button> {/* Render each TextBox-Toolbar pair */} {this.state.textBoxes.map(textBox => ( <div key={textBox.id} className="text-box-pair"> <TextBox id={textBox.id} content={textBox.content} onChange={(newContent) => this.updateTextBoxContent(textBox.id, newContent)} /> <Toolbar textBoxId={textBox.id} onToolbarAction={(action) => this.handleToolbarAction(textBox.id, action)} /> </div> ))} </div> ); } // Handle toolbar actions (e.g., bold, italic) for a specific TextBox handleToolbarAction = (textBoxId, action) => { this.setState(prevState => ({ textBoxes: prevState.textBoxes.map(textBox => { if (textBox.id === textBoxId) { // Replace with your DraftJS-specific content modification logic const updatedContent = modifyContentWithAction(textBox.content, action); return { ...textBox, content: updatedContent }; } return textBox; }) })); }; }
Step 2: Update TextBox Component to Sync with Parent State
Your DraftJS-based TextBox needs to accept the id and onChange prop, then trigger the callback whenever its content changes. We'll also sync parent state updates back to the editor.
import { Editor, EditorState, convertToRaw, convertFromRaw } from 'draft-js'; class TextBox extends React.Component { constructor(props) { super(props); this.state = { editorState: EditorState.createWithContent(convertFromRaw(props.content)) }; } // Sync editor changes to parent state onEditorChange = (editorState) => { this.setState({ editorState }); const rawContent = convertToRaw(editorState.getCurrentContent()); this.props.onChange(rawContent); }; // Sync parent content updates to the editor componentDidUpdate(prevProps) { if (prevProps.content !== this.props.content) { const newEditorState = EditorState.createWithContent(convertFromRaw(this.props.content)); this.setState({ editorState: newEditorState }); } } render() { return ( <div className="text-box"> <Editor editorState={this.state.editorState} onChange={this.onEditorChange} // Add your custom DraftJS props here /> </div> ); } }
Step 3: Update Toolbar Component to Target Specific TextBox
Your Toolbar will receive the textBoxId and onToolbarAction prop. When a user clicks a toolbar button, it passes the action and target ID back to the parent App.
class Toolbar extends React.Component { triggerAction = (action) => { this.props.onToolbarAction(action); }; render() { return ( <div className="toolbar"> <button onClick={() => this.triggerAction('bold')}>Bold</button> <button onClick={() => this.triggerAction('italic')}>Italic</button> <button onClick={() => this.triggerAction('insert-link')}>Insert Link</button> {/* Add other toolbar controls as needed */} </div> ); } }
Key Concepts Explained
- Unique IDs: Each pair gets a unique
id(we useDate.now()for simplicity, but you could use UUIDs too). This lets the parent know exactly which text box to update when a toolbar action fires. - Parent as Middleman: React relies on top-down data flow, so the
Appholds all text box state. Both child components communicate with it via props, avoiding messy direct child-to-child interaction. - DraftJS Sync: We convert between DraftJS's
EditorStateand raw JSON to keep the parent state in sync with the editor—this is standard for integrating DraftJS in component hierarchies.
内容的提问来源于stack exchange,提问作者Reenergy

