React点击编辑字段的模式

huangapple go评论54阅读模式
英文:

React pattern for click-to-edit fields

问题

I'm using React 18 with functional components and I'm looking for a clean reusable pattern for "click to edit" UIs. This is the UI paradigm where:

  1. You have some text.
  2. On hover of the text, it shows visual treatment indicating the field is editable.
  3. On click on the text, the text is swapped for an input field allowing you to edit the text.
  4. On blur of the input, a callback is made to automatically save changes back to the DB and toggle the input back to text.

I can do this per input field, but I'm trying to figure out a reusable React component that I can configure with the "view" render, the "edit" render, and any callbacks. Part of this is because my inputs will change quite a bit across my app; so I'll have inputs, textareas, select fields, etc. Right now, I'm duplicating tons of code implementing a component for every "editable field."

I was playing around with something like:

<Editable>
  <p>{value}</p>
  <>
    <label>Update the value:</label>
    <input type="text"/>
  </>
</Editable>

...and then access the "view" stage in Editable via children[0] and the edit state via children[1]... but I'm not sure how to attach handlers to children and its subelements (for example, I'd want to always have children[0].onClick={() => setEditing(true) } and the children[1]'s input to have children[1].onBlur{() => setEditing(false) }... or something like that. Also, I'm not sure if I can figure out what elements of children to attach the handlers to if I can even do that programmatically.

英文:

Im using React 18 w/ functional components, and am looking for a clean re-usable pattern for "click to edit" UIs - this is the UI paradigm where:

  1. You have some text
  2. Onhover of text, it shows visual treatment indicating the field is editable
  3. OnClick on text, the text is swapped for an input field allowing you to edit the text
  4. OnBlur of the input, a callback is made to automatically save changes back to the DB and toggle the input back to text

I can do this per input field, but im trying to figure out an a re-usable React component that i can configure w/ the "view" render, the "edit" render, and any callbacks. Part of this is because my inputs will change quite a bit across my app; so ill have inputs, textareas, select fields, etc. Right now, im duplicating tons of code implementing a component for every "editable field".

I was playing around with something like:

&lt;Editable&gt;
  &lt;p&gt;{value}&lt;/p&gt;
  &lt;&gt;
    &lt;label&gt;Update the value:&lt;/label&gt;
    &lt;input type=&quot;text&quot;/&gt;
  &lt;/&gt;
&lt;/Editable&gt;

...and then access the "view" stage in Editable via children[0] and the edit state via children[1]... but im not sure how to attach handlers to children and its subelements (for example, i'd want to always have children[0].onClick={() =&gt; setEditing(true) } and the children[1]&#39;s input to have children[1].onBlur{() => setEditing(false) }` .. or something like that. Also im not sure if i can figure out what elements of children to attach the handlers to if i can even do that programmatically.

答案1

得分: 2

以下是代码的中文翻译:

import React from 'react';
import './style.css';

let Editable = (props) => {
  let [mode, setMode] = React.useState('view');
  let [value, setValue] = React.useState('Hello');
  // 可能还有其他逻辑...
  return props.children({ mode, setMode, value, setValue });
};

export default function App() {
  return (
    <div>
      <Editable>
        {({ mode, setMode, value, setValue }) => {
          return mode === 'view' ? (
            <p
              onClick={() => {
                setMode('edit');
              }}
            >
              {value}
            </p>
          ) : mode === 'edit' ? (
            <div>
              <input
                onBlur={() => {
                  setMode('view');
                }}
                value={value}
                onChange={(e) => setValue(e.target.value)}
              />
            </div>
          ) : null;
        }}
      </Editable>
    </div>
  );
}

希望这对您有所帮助!如果您需要任何进一步的信息,请告诉我。

英文:

Something like this?

import React from &#39;react&#39;;
import &#39;./style.css&#39;;

let Editable = (props) =&gt; {
  let [mode, setMode] = React.useState(&#39;view&#39;);
  let [value, setValue] = React.useState(&#39;Hello&#39;);
  // Some other logic maybe ...
  return props.children({ mode, setMode, value, setValue });
};

export default function App() {
  return (
    &lt;div&gt;
      &lt;Editable&gt;
        {({ mode, setMode, value, setValue }) =&gt; {
          return mode === &#39;view&#39; ? (
            &lt;p
              onClick={() =&gt; {
                setMode(&#39;edit&#39;);
              }}
            &gt;
              {value}
            &lt;/p&gt;
          ) : mode === &#39;edit&#39; ? (
            &lt;div&gt;
              &lt;input
                onBlur={() =&gt; {
                  setMode(&#39;view&#39;);
                }}
                value={value}
                onChange={(e) =&gt; setValue(e.target.value)}
              /&gt;
            &lt;/div&gt;
          ) : null;
        }}
      &lt;/Editable&gt;
    &lt;/div&gt;
  );
}

This approach is called render props. It allows to have your custom logic inside the component, and delegate rendering part to the user (while letting the user to consume the custom logic from the component).

huangapple
  • 本文由 发表于 2023年5月14日 04:28:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76244742.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定