You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将子组件函数传递给父组件?多TextBox对应Toolbar场景

Solution: Pairing Each TextBox with Its Own Toolbar in React

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 use Date.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 App holds 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 EditorState and raw JSON to keep the parent state in sync with the editor—this is standard for integrating DraftJS in component hierarchies.

内容的提问来源于stack exchange,提问作者Reenergy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:48:52