最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - need something like event.target.focus() in React - Stack Overflow

programmeradmin6浏览0评论

I'm creating a dynamic list ponent that basically renders a new empty text field every time something is added to the list. The ponent is as follows (it uses a custom TextFieldGroup but I don't think that code is necessary as nothing out of the ordinary is going on.):

const DynamicInputList = ({ inputs, onChangeArray, label, name, errors }) => 
{
  const nonEmptyInputs = inputs.filter(input => {
    return input !== "";
  });
  const lastIndex = nonEmptyInputs.length;
  return (
    <div>
      {nonEmptyInputs.map((input, index) => {
        return (
          <Grid container spacing={16} key={index}>
            <Grid item xs={12}>
              <TextFieldGroup
                label={label}
                id={`${name}${index}`}
                name={name}
                value={input}
                onChange={e => onChangeArray(e, index)}
                errors={errors[name]}
              />
            </Grid>
          </Grid>
        );
      })}
      <Grid container spacing={16} key={lastIndex}>
        <Grid item xs={12}>
          <TextFieldGroup
            label={label}
            id={`${name}${lastIndex}`} 
            name={name}
            value={inputs[lastIndex]}
            onChange={e => onChangeArray(e, lastIndex)}
            errors={errors[name]}
          />
        </Grid>
      </Grid>
    </div>
  );
};

The onChangeArray function is as follows:

  onChangeArray = (e, index) => {
    const state = this.state[e.target.name];
    if (e.target.value === "") {
      state.splice(index, 1);
      this.setState({ [e.target.name]: state });
    } else {
      state.splice(index, 1, e.target.value);
      this.setState({ [e.target.name]: state });
    }
  };

Everything works fine except when a blank field is changed (begin to type) it immediately removes focus from any of the fields. I'm looking for a way to keep the focus on this field while still adding the new one below.

Thanks in advance.

I'm creating a dynamic list ponent that basically renders a new empty text field every time something is added to the list. The ponent is as follows (it uses a custom TextFieldGroup but I don't think that code is necessary as nothing out of the ordinary is going on.):

const DynamicInputList = ({ inputs, onChangeArray, label, name, errors }) => 
{
  const nonEmptyInputs = inputs.filter(input => {
    return input !== "";
  });
  const lastIndex = nonEmptyInputs.length;
  return (
    <div>
      {nonEmptyInputs.map((input, index) => {
        return (
          <Grid container spacing={16} key={index}>
            <Grid item xs={12}>
              <TextFieldGroup
                label={label}
                id={`${name}${index}`}
                name={name}
                value={input}
                onChange={e => onChangeArray(e, index)}
                errors={errors[name]}
              />
            </Grid>
          </Grid>
        );
      })}
      <Grid container spacing={16} key={lastIndex}>
        <Grid item xs={12}>
          <TextFieldGroup
            label={label}
            id={`${name}${lastIndex}`} 
            name={name}
            value={inputs[lastIndex]}
            onChange={e => onChangeArray(e, lastIndex)}
            errors={errors[name]}
          />
        </Grid>
      </Grid>
    </div>
  );
};

The onChangeArray function is as follows:

  onChangeArray = (e, index) => {
    const state = this.state[e.target.name];
    if (e.target.value === "") {
      state.splice(index, 1);
      this.setState({ [e.target.name]: state });
    } else {
      state.splice(index, 1, e.target.value);
      this.setState({ [e.target.name]: state });
    }
  };

Everything works fine except when a blank field is changed (begin to type) it immediately removes focus from any of the fields. I'm looking for a way to keep the focus on this field while still adding the new one below.

Thanks in advance.

Share Improve this question asked Jul 24, 2018 at 20:20 Adam JohnstonAdam Johnston 1,4112 gold badges13 silver badges24 bronze badges 1
  • please elaborate it.. Everything works fine except when a blank field is changed (begin to type) it immediately removes focus from any of the fields. – Shubham Agarwal Bhewanewala Commented Jul 24, 2018 at 20:54
Add a ment  | 

1 Answer 1

Reset to default 2

The problem is that you're encountering the following sequence of events (assuming inputs length of 5):

  1. React renders 1 field (key = 5)
  2. User starts typing 'a'
  3. Your state change is triggered
  4. React renders 2 entirely new fields (key = 1 & value = 'a', key = 5) and trashes the old one (key = 5)

There are at least two solutions

Don't delete / trigger re-render of the original field

This is the cleaner solution.

First, you are directly mutating state in onChangeArray with your use of slice, because that does an in-place modification. Perhaps this isn't causing problems now, but it's a big React anti-pattern and could create unpredictable behavior.

Here's a quick fix:

  onChangeArray = (e, index) => {
    const state = [...this.state[e.target.name]];
    if (e.target.value === "") {
      state.splice(index, 1);
      this.setState({ [e.target.name]: state });
    } else {
      state.splice(index, 1, e.target.value);
      this.setState({ [e.target.name]: state });
    }
  };

And other options

I'll leave the reworking of the implementation to you, but the gist would be:

  1. Use consistent key references, which means iterate over all your inputs and just skip the empty ones instead of finding the empty ones first and setting that arbitrary key to the total length. Of course, you should still render the first empty one.
  2. You could consider rendering everything, and use CSS display:none attribute as needed to acplish your desired UX

Leverage input's autofocus attribute

I assume your TextFieldGroup uses an input element. You could pass the autofocus attribute to the field you want to have focus. This answers your original question.

But this isn't remended, as you're still needlessly running through those re-render cycles and then putting a patch on top.

发布评论

评论列表(0)

  1. 暂无评论