【问题标题】:How do I dynamically display the value of a textarea in a separate div using React?如何使用 React 在单独的 div 中动态显示 textarea 的值?
【发布时间】:2021-03-27 10:56:54
【问题描述】:

我正在使用 React(初学者)开发降价预览器,并且我试图在页面上的单独 div 中显示 textarea 的当前值。我不确定如何最好地使用 React 处理 textarea 值。

我的组件层次结构如下:

  • 应用程序
    • 编辑器
      • 工具栏
      • 文本区域
    • 预览器
      • 工具栏
      • 目标分区

目前,我的 App 组件中有一个函数可以处理对 textarea 的更改 - 它作为道具传递给 Editor 组件,并进一步传递给 Textarea 组件,在 onChange 事件之后调用它:

function App() {
  const handleTextChange = () => {
    const textarea = document.getElementById("textarea");
    let text;
    if (textarea === null) {
      text = "";
    } else {
      text = textarea.value;
    }
    console.log(text);
    return text;
  };

  return (
    <div className="App">
      <Header />
      <div className="App-body">
        <Editor handleTextChange={handleTextChange} />
        <Preview />
      </div>
    </div>
  );
}

export default App;

这个功能正在工作 - 我可以在我输入时看到控制台中的 textarea 值正在更新。

问题如下:

  • 我应该如何将此值传递给目标 div?这是否需要涉及 State,以便每次 textarea 值更改时目标 div 重新渲染?
  • 在我的 App 组件中声明 handleTextChange 函数是正确的方法吗?有没有更好的方法来实现这个结果?

React 新手(和 Stack Overflow) - 任何建议(或相关问题的链接)表示赞赏

【问题讨论】:

  • 你对初学者来说做得很好,特别是因为你挑战了你所做的假设,这是一个常见的陷阱。是的,在 App 组件中声明 handleTextChange 函数是一种反模式;现在,在提供替代方案之前,我想建议您首先成功实现这个问题的目标,并达到您对正在执行的 DOM 和状态管理感到满意的程度,只是为了降低复杂性,然后采取看看钩子。 React 中的 Hooks 允许任何两个组件(无论父子关系如何)共享数据和功能。

标签: javascript reactjs textarea


【解决方案1】:

我应该如何将此值传递给目标 div?这是否需要涉及State,以便每次textarea值更改时目标div重新渲染?

这将是通常的方式,是的。

在我的 App 组件中声明 handleTextChange 函数是正确的方法吗?有没有更好的方法来达到这个结果?

handleTextChange 很好,但问题是你如何访问文本区域。一般来说,你不应该为此而去 DOM。相反,将textarea 设为controlled component(因此其值保持在状态中),并在渲染textarea 时使用该状态, 在渲染预览div 时使用该状态。

这是一个非常基本的例子:

const {useState} = React;

// The `Editor` component receives the value and the change function as
// props. I've called the change function `handleTextChange` so you can
// see how it relates to your code, but I might well have called it
// `setValue` otherWise.
const Editor = React.memo(({value, handleTextChange}) => {
    // Our change handler just extracts the value from the textarea
    // and passes it on. No need to memoize it here, probably,
    // but if you wanted to you could use `useCallback` with the
    // dependency array [handleTextChange].
    const onChange = e => handleTextChange(e.target.value)
    return (
        <textarea
            value={value}
            onChange={e => handleTextChange(e.target.value)}
        />
    );
});

// The Preview component shows the text
const Preview = ({text}) => {
    return <div>{text}</div>;
};

// Just a stand-in
const Header = () => <div>(Header)</div>;

function App() {
    // The state for the text and its setter
    const [text, setText] = useState("");
  
    // Notice how we can pass the state setter directly to `Editor`
    // as `handleTextChange` below.
    return (
        <div className="App">
            <Header />
            <div className="App-body">
                <Editor handleTextChange={setText} />
                <Preview text={text} />
            </div>
        </div>
    );
}

ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>

【讨论】:

  • 谢谢。请您澄清一下,如果handleTextChange 保留在父组件中,并且textarea 成为受控组件(感谢该链接),我如何将该状态传递给预览div?是作为道具传递的吗?
  • @wrufusii - 是的,没错。我在答案中添加了一个简单的示例,并附有一些内联解释。编码愉快!
【解决方案2】:

首先,您有两种类型的组件:ES6 类组件(可以通过 this.state 使用状态)和您的情况下的功能组件。功能组件不能使用 React 状态,但在 React 中引入了一个新功能,称为反应挂钩(useState hook)。在您的情况下,您需要在应用程序组件中使用状态变量,然后通过道具将此状态传递给您的组件。您需要设置组件的状态,并在您的 handleText 更改函数中将其作为道具传递给您的预览组件。

【讨论】:

    猜你喜欢
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 2023-04-02
    • 1970-01-01
    相关资源
    最近更新 更多