Счетчик слов с React - PullRequest
       48

Счетчик слов с React

0 голосов
/ 26 сентября 2018

Я пытаюсь написать счетчик слов с React.Идея состоит в том, что, как только вы превысите максимальное количество слов, появится предупреждение, и пользователь не сможет вставить больше символов.Моя идея состояла в том, чтобы использовать атрибут maxlength.После того, как необходимые слова и написанные слова будут одинакового количества, будут подсчитаны символы и активирован атрибут maxlength через состояние.

Атрибут maxlength не работает должным образом.Как я могу это исправить?

HTML

<div id="app"></div>

REACT

class MyComponent extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      firstValue: '',
      secondValue: '',
      needWords: '',
      wordCount: '',
      limWords: null,
    }
    this.firstHandle = this.firstHandle.bind(this)
    this.handleSubmit = this.handleSubmit.bind(this)
    this.secondHandle = this.secondHandle.bind(this)    
  }
  firstHandle(e){
    this.setState({
      firstValue: e.target.value
    })
  }

  handleSubmit(e){
    e.preventDefault()
    this.setState({
      needWords: this.state.firstValue
    })
  }

  secondHandle(event){
    this.setState({
      secondValue: event.target.value,
      wordCount: event.target.value === '' ? 0 : this.state.secondValue.split(' ').length,
      limWords: (this.state.needWords - this.state.wordCount) < 0 ? this.state.secondValue.length : null
    })

  }

  render(){
    var result = this.state.needWords - this.state.wordCount;
    let tooManyChars;
    if (result < 0){
      const tooManyCharStyle = {
        color: 'red'
      }
      tooManyChars = <p style={tooManyCharStyle}>You exceeded the maximum number of words!!</p>;
    }
    return(
     <div>
      <form onSubmit={this.handleSubmit}>
        <p>How many words do you have to write?</p>
        <input 
          type="text" 
          value={this.state.firstValue}
          onChange={this.firstHandle}></input>
        <button type="submit">Go</button>
      </form>
      <form>
        <p>You still have to write {result} words</p>
        <textarea 
          type="text"
          value={this.state.value}
          onChange={this.secondHandle}
          maxLength={this.state.limWords}>
        </textarea>
        { tooManyChars }
       </form>
      </div>
    );
  }
}

ReactDOM.render(<MyComponent/>, document.getElementById('app'));

Ответы [ 3 ]

0 голосов
/ 26 сентября 2018

maxLength принимает максимальное количество символов, допустимое в этом поле, например,

<input type="text" maxLength={10} />

допускает максимум 10 символов (не слов) в поле.

Вам необходимо изменитьваш метод onChange для отслеживания изменений в поле и принятия новых символов (но не для принятия пробелов, поскольку это диктует новое слово).Таким образом, вы можете добавить условное выражение так:

secondHandle(event){

    if(event.target.value.split(' ').length > this.state.needWords) {
        event.target.value = event.target.value.trimRight();
    } else {
        this.setState({
            secondValue: event.target.value,
            wordCount: event.target.value === '' ? 0 : this.state.secondValue.split(' ').length,
            limWords: (this.state.needWords - this.state.wordCount) < 0 ? this.state.secondValue.length : null
        });
    }
}
0 голосов
/ 26 сентября 2018

Как объяснено в , этот ответ , maxlength применяется только к пользовательскому вводу, а не к программно установленным значениям.

Чтобы охватить оба, secondValue должен быть усечен сsubstr либо в обработчике изменений, либо в render.maxlength является необязательным, поскольку при изменении поля будет обрабатываться слишком большая длина.

0 голосов
/ 26 сентября 2018

Вы допустили пару ошибок в своем коде.Первое, что вам нужно понять, это setState is asynchronous, и если вам нужно использовать текущие значения, используйте их напрямую.для текстовой области вам нужно передать this.state.secondValue вместо this.state.value, а также есть пара других ошибок.вот рабочий код.

   class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      firstValue: "",
      secondValue: "",
      needWords: "",
      wordCount: "",
      limWords: null
    };
    this.firstHandle = this.firstHandle.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.secondHandle = this.secondHandle.bind(this);
  }
  firstHandle(e) {
    this.setState({
      firstValue: e.target.value
    });
  }

  handleSubmit(e) {
    e.preventDefault();
    this.setState({
      needWords: this.state.firstValue,
      secondValue: ""
    });
  }

  secondHandle(event) {
    //calculate the word count first itself and use them in other manipulations
    const wordCount =
      event.target.value === "" ? 0 : event.target.value.split(" ").length;
    this.setState({
      secondValue: event.target.value,
      wordCount: wordCount,
      limWords:
        this.state.needWords - wordCount < 0
          ? this.state.secondValue.length
          : null
    });
  }

  render() {
    var result = this.state.needWords - this.state.wordCount;
    let tooManyChars;
    if (result < 0) {
      const tooManyCharStyle = {
        color: "red"
      };
      tooManyChars = (
        <p style={tooManyCharStyle}>
          You exceeded the maximum number of words!!
        </p>
      );
    }
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <p>How many words do you have to write?</p>
          <input
            type="text"
            value={this.state.firstValue}
            onChange={this.firstHandle}
          />
          <button type="submit">Go</button>
        </form>
        <form>
          <p>You still have to write {result} words</p>
          <textarea
            type="text"
            value={this.state.secondValue}
            onChange={this.secondHandle}
            maxLength={this.state.limWords}
          />
          {tooManyChars}
        </form>
      </div>
    );
  }
}

вот живой рабочий пример: https://codesandbox.io/s/pk085z3rk7

...