Как получить значения из динамически создаваемых входов с ReactJS - PullRequest
0 голосов
/ 25 мая 2018

У меня есть добавленные данные на моей странице, основанные на периоде времени, например, если период - неделя, у меня будет 7 текстовых вводов, если период - две недели, у меня будет 15 текстовых вводов, которые я уже сделал, что этоТеперь это не проблема. Я хочу получить значения, введенные в созданные текстовые поля, зная, что в моем рендере есть только один вход, который дублируется несколько раз в соответствии с заданным периодом

.мои данные

render() {
    const days = [];
    let day = this.props.StartOfWeek;
    while (day <= this.props.EndOfWeek) {
      days.push(moment(day).format('ddd, DD-MM'));
      day = day.clone().add(1, 'd');
    }
    const daysCode = days.map((displayedDay) => {
    return (
        <td className={this.isWeek(displayedDay)}>
          <tr>{displayedDay}</tr>
          <tr>  <input type="text" key={displayedDay.id} size="3" /></tr>
        </td>);
    });

есть идеи, как мне действовать?

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

Я нашел решение, это было так глупо, используя jquery

  $('.App input').each((index, input) => {
  alert(input.value);

}

0 голосов
/ 25 мая 2018

Самый простой способ, используя функцию стрелки:

class InputsList extends React.Component {

    render() {
        const items = this.props.fields.map((field, i) => (
            <YourInputComponent onChange={
                (e) => this.props.onChange(i, e.target.value) } />
        );

        return (<div>{ items }</div>);
    }
} 

Проблема этого подхода заключается в том, что функция стрелки внутри onChange будет перераспределять новую функцию каждый раз, когда вызывается метод render.Это может вызвать проблемы с производительностью из-за:

  • Чистые компоненты будут рендериться снова, так как старая функция (стрелка) и новая функция (стрелка) будут отличаться, даже если оба будут вызывать одну и ту же функцию.
  • Затраты на сборщик мусора для избавления от этих старых функций.

Лучшим подходом будет передача любых соответствующих данных до YourInputComponent, который будет отвечать за вызовonChange с соответствующим индексом / идентификатором, который позволяет вам определить, какой вход вызвал событие.

class InputsList extends React.Component {

    render() {
        const items = this.props.fields.map((field, i) => (
            <YourInputComponent index={ i } onChange={ this.props.onChange } />
        );

        return (<div>{ items }</div>);
    }
}

В YourInputComponent у вас будет что-то вроде этого:

this.props.onChange(this.props.index, e.target.value);

Сейчасфункция, которую вы передаете onChange, всегда будет одинаковой, если только она не изменится в родительском компоненте, поэтому YourInputComponent не будет перерисована.

Здесь у вас есть рабочий примерпервого метода:

class List extends React.PureComponent {
  render() {
    const { values, length } = this.props;
    const items = [];
    
    for (let i = 0; i < length; ++i) {
      const value = values[i];
      
      items.push(<li key={ `${ value }-${ i }` } className="list__item">{ value }</li>);
    }
    
    return (<ul>{ items }</ul>);
  }
}

class InputsList extends React.PureComponent {

  render() {
    const { name, label, totalInputs, onChange } = this.props;
    const inputs = [];

    for (let i = 0; i < totalInputs; ++i) {
      inputs.push(
        <li key={ i }>
          <label className="inputs__label">
            { `${ label } ${ i + 1 }` }
            
            <input
              className="inputs__input"
              type='text'
              name={ `${ name }-${ i }` } 
              onInput={ (e) => onChange(i, e.target.value) } />
          </label>
        </li>
      );
    }

    return (<ul>{ inputs }</ul>);
  }
}

class RadioTabs extends React.PureComponent {

  render() {   
    const { name, value, options, onChange } = this.props;
  
    const radios = options.map(option => (
      <li key={ option }>
        <label className="radioTabs__label">
          <input
            className="radioTabs__input"
            type="radio"
            value={ option }
            checked={ value === option }
            name={ name }
            onChange={ onChange } />
            
            <span className="radioTabs__text">{ option }</span>
        </label>
      </li>
    ));
  
    return(
      <ul className="radioTabs__base">
        { radios }
      </ul>
    );
  }
}

class App extends React.Component {

  static options = [1, 2, 3, 4, 5, 6, 7];

  constructor(props) {
    super(props);
    
    this.state = {
      totalInputs: App.options[0],
      values: [],
    };
  }
  
  onTotalInputsChange = (e) => {    
    this.setState({
      totalInputs: parseInt(e.target.value),
      values: this.state.values,
    });
  };
  
  onInputsChange = (index, value) => {
    const values = [ ...this.state.values ];
    
    values[index] = value;
    
    this.setState({
      totalInputs: this.state.totalInputs,
      values,
    });
  };
  
  render() {
  
    const { totalInputs, values }  = this.state;
  
    return(
      <div className="app">
        <div className="header">
          <RadioTabs
            name="days"
            value={ totalInputs }
            options={ App.options }
            onChange={ this.onTotalInputsChange } />
        </div>

        <div className="columns">
          <div className="left">
            <InputsList
              name="values"
              totalInputs={ totalInputs }
              label="Day"
              onChange={ this.onInputsChange } />
          </div>

          <div className="right">
            <List values={ values } length={ totalInputs }/>
          </div>
        </div>
      </div>
    );
  }
}


ReactDOM.render(<App />, document.getElementById('app'));
body {
  font-family: monospace;
  margin: 0;
}

ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.app {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.header {
  padding: 4px;
  border-bottom: 2px solid black;
  flex: 0 0 auto;
}

.columns {
  display: flex;
  flex: 1 1 auto;
}

.left,
.right {
  flex: 1 0 0;
  overflow-y: scroll;
  padding: 4px;
}

.left {
  border-right: 2px solid black;
}

/* RADIO TABS */

.radioTabs__base {
  display: flex;
  align-items: center;
}
.radioTabs__label {
  display: block;
  padding: 4px 0;
  cursor: pointer;
  border-radius: 2px;
  min-height: 27px;
  min-width: 35px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.radioTabs__label:hover {
  background: #EEE;
}

.radioTabs__input {
  display: none;
}

.radioTabs__text {
  display: block;
  padding: 2px 4px 0;
  border-bottom: 2px solid transparent;
}

.radioTabs__input:checked + .radioTabs__text {
  border-bottom-color: black;
}

/* INPUTS LIST */

.inputs__label {
  display: block;
  padding: 4px 8px;
  cursor: pointer;
  border-radius: 2px;
  display: flex;
  align-items: center;
}

.inputs__label:hover {
  background: #EEE;
}

.inputs__input {
  border: 2px solid black;
  padding: 4px 8px;
  margin: 0 0 0 8px;
  font-family: monospace;
  flex: 1 0 auto;
}

/* LIST */

.list__item {
  border-bottom: 2px solid black;
  line-height: 33px;
  height: 33px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
<div id="app"></div>

<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...