Текстовое поле, отображающее неправильное количество символов в ReactJS

#javascript #reactjs

#javascript #reactjs

Вопрос:

У меня есть текстовое поле, в котором я показываю количество символов внизу. Я передаю ответ от API в качестве реквизита, поскольку хочу отобразить количество символов. Моя функция onChange работает правильно, я не передаю данные в качестве реквизита. Я обновляю свой компонент, когда получаю ответ API с помощью useEffect.

Но я столкнулся с проблемой со счетчиком, и он отображает счетчик неправильно. Я прикрепил фрагмент компонента React.

 class TextAreaComponent extends React.Component {
constructor(props) {
  super(props);
  this.state = {
    characterCount: '1500'
  };
}

  handleWordCount = (e) => {
    const charCount = e.target.value.length;
    const maxCharCount = e.target.getAttribute("max-length");
    const charLeft = maxCharCount - charCount;
    this.setState({
      characterCount: charLeft
    });
  }

render() {

const { data } = this.props;
// Binding the data in value,
  return (
        <div className="personal-bio">
            <h4>Bio</h4>
            <textarea onChange={this.handleWordCount} value={data amp;amp; data.length > 0 ? data : ""} max-length="1500" name="textarea" placeholder="Tell me about yourself"></textarea>
              <p className="user-bio-char-limit">Total Character limit : {this.state.characterCount}</p>
            </div>
        )
  }
}

// Passing the response data as props
ReactDOM.render(
  <TextAreaComponent data="Hello, this is my bio" />, document.body
); 
 textarea {
border: 1px solid #222;
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div> 

Ответ №1:

Здесь есть 2 проблемы. Во-первых, вы не обновляете textarea значение при изменении. Вторая проблема заключается в том, что вам также нужно вычислять количество, когда результаты поступают из API. вы можете выполнить эту работу в функции componentDidUpdate жизненного цикла, но поскольку у меня нет доступа к API, я буду использовать componentDidMount только для того, чтобы показать, что вы должны делать.

 class TextAreaComponent extends React.Component {
constructor(props) {
  super(props);
  this.state = {
    characterCount: '1500',
    data: ""
  };
}

componentDidMount() {
    const charCount = this.props.data.length;
    const maxCharCount = this.state.characterCount;
    const charLeft = maxCharCount - charCount;
    this.setState({
      characterCount: charLeft,
      data: this.props.data
    });
}

handleWordCount = (e) => {
    const charCount = e.target.value.length;
    const maxCharCount = e.target.getAttribute("max-length");
    const charLeft = maxCharCount - charCount;
    this.setState({
      characterCount: charLeft,
      data: e.target.value
    });
 }

render() {

const { data } = this.state;
// Binding the data in value,
  return (
        <div className="personal-bio">
            <h4>Bio</h4>
            <textarea onChange={this.handleWordCount} value={data amp;amp; data.length > 0 ? data : ""} max-length="1500" name="textarea" placeholder="Tell me about yourself"></textarea>
              <p className="user-bio-char-limit">Total Character limit : {this.state.characterCount}</p>
            </div>
        )
  }
}

// Passing the response data as props
ReactDOM.render(
  <TextAreaComponent data="Hello, this is my bio" />, document.body
); 
 textarea {
border: 1px solid #222;
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div> 

Комментарии:

1. Мы все еще можем вводить ниже достигнутого максимального предела. оно становится отрицательным…

Ответ №2:

Количество символов изначально неверно, потому что вы жестко кодируете его как 1500 вместо 1500 - props.data.length . Тем не менее, this.state.characterCount это, по-видимому, вычисленное значение, которое не нужно сохранять в состоянии. Я бы рекомендовал сохранить состояние value in, поскольку это часть, которая действительно меняется. Затем вы можете вычислить оставшиеся символы непосредственно в части визуализации вашего компонента. Вот упрощенный функциональный компонент:

 const MAX_LENGTH = 1500;

const TextAreaComponent = ({ data }) => {
  // Set the value of `data` as the initial value of the textarea.
  const [value, setValue] = useState(data);

  return (
    <div className="personal-bio">
      <h4>Bio</h4>
      <textarea
        max-length={MAX_LENGTH}
        name="textarea"
        onChange={(e) => setValue(e.target.value)}
        placeholder="Tell me about yourself"
        value={value}
      />
      <p className="user-bio-char-limit">
        Remaining characters: {MAX_LENGTH - value.length}
      </p>
    </div>
  );
};
 

Рабочая изолированная среда: https://codesandbox.io/s/ecstatic-poitras-8gbwd

Обновление: вот пример, в котором состояние полностью контролируется родительским. Намного проще, поскольку компонент Textarea просто реагирует на изменения реквизита, а не на синхронизацию состояния и реквизита.

 const TextAreaComponent = ({ data, onChange }) => (
  <div className="personal-bio">
    <h4>Bio</h4>
    <textarea
      max-length={MAX_LENGTH}
      name="textarea"
      onChange={onChange}
      placeholder="Tell me about yourself"
      value={data}
    />
    <p className="user-bio-char-limit">
      Remaining characters: {MAX_LENGTH - data.length}
    </p>
  </div>
);

const Parent = () => {
  const [data, setData] = useState('Hello, this is my bio');

  useEffect(() => {
    // Make your API call here and update state using `setData`
    // when the request finishes.
  }, []);

  return (
    <TextAreaComponent data={data} onChange={(e) => setData(e.target.value)} />
  );
};
 

Комментарии:

1. Могу ли я установить состояние в useEffect … Поскольку данные, переданные в качестве реквизитов из api, будут переданы после монтирования компонента. Передача данных в качестве второго аргумента в useEffect. Я прав?

2. @tkamath99: похоже, вы уже устанавливаете состояние, используя эффект в родительском элементе, когда запрос API завершается. Если это так, вы можете рассмотреть возможность использования родительского элемента управления состоянием, чтобы компонент Textarea просто реагировал на изменения реквизита. Это было бы намного проще.

3. @tkamath99: я обновил свой ответ, чтобы отразить мой комментарий выше.