2016-12-23 1 views
0

Во время работы над моим приложением я узнал, что способ, которым я его настроил сейчас, на самом деле не идеален. В настоящее время я сохраняю значения двух динамически созданных полей ввода в двух отдельных массивах. Теперь, поскольку я понимаю, что это не очень умно, потому что оба поля ввода имеют один и тот же индекс и фактически принадлежат друг другу.Можно ли объединить эти два массива в один объект с помощью React и Javascript?

Теперь мне было интересно, как я могу изменить свой код, чтобы сохранить оба значения в одном и том же объекте.

Это мой код для моей динамичной формы:

class MediaInput extends React.Component { 
 
    render() { 
 
    const linkName = `link${this.props.index}`; 
 
    const contentName = `content${this.props.index}`; 
 

 
    return (
 
     <div> 
 
     <ControlLabel>Media (optional)</ControlLabel> 
 
     <input 
 
     onChange={(event) => this.props.handleChangeUrl(event, this.props.index)} 
 
     name={ linkName } 
 
     value={ this.props.mediaUrls[this.props.index]} 
 
     className="form-control" 
 
     placeholder="Add your media url. We accept YouTube, Vimeo and SoundCloud links" 
 
     type="text" 
 
     /> 
 
     <input 
 
     name={ contentName } 
 
     onChange={(event) => this.props.handleChangeContent(event, this.props.index)} 
 
     value={ this.props.mediaContents[this.props.index]} 
 
     className="form-control" 
 
     placeholder="Add your media content" 
 
     type="text" 
 
     /> 
 
    </div> 
 
    ); 
 
    } 
 
}

Это мое текущее состояние:

this.state ={ 
 
     mediaFields: [], 
 
     content: [], 
 
     mediaUrls: [ null, null, null ], 
 
     mediaContents: ['', '', ''], 
 
    };

Это мои функции:

// Add/remove media fields 
 

 
    add() { 
 
    event.preventDefault(); 
 
    const mediaFields = this.state.mediaFields.concat(MediaInput); 
 
    if (i < 3) { 
 
     this.setState({ mediaFields }); 
 
     i++ 
 
    } else { 
 
     Bert.alert('Only 3 media links are allowed', 'danger'); 
 
    } 
 
    } 
 

 
    remove() { 
 
    event.preventDefault(); 
 
    const lastElement = this.state.mediaFields.pop(); 
 
    const mediaFields = this.state.mediaFields; 
 
    this.setState({ mediaFields }); 
 
    i-- 
 
    } 
 

 
// Handle change media fields 
 

 
    handleChangeUrl(e, index) { 
 
    // Shallow copy of array 
 
    const mediaUrls = this.state.mediaUrls.slice(); 
 
    let url = e.target.value 
 
    if (!/^https?:\/\//i.test(url)) { 
 
     url = 'http://' + url; 
 
    } 
 

 
    mediaUrls[index] = url; 
 
     this.setState({ mediaUrls}); 
 
    } 
 

 
    handleChangeContent(e, index) { 
 
    // Shallow copy of array 
 
    const mediaContents = this.state.mediaContents.slice(); 
 
    mediaContents[index] = e.target.value; 
 
     this.setState({ mediaContents }); 
 
    }

И это является частью формы, где я добавить поля ввода:

[...] 
 
    
 
const mediaFields = this.state.mediaFields.map((Element, index) => { 
 
     return <Element key={ index } index={ index } mediaUrls={this.state.mediaUrls} mediaContents={this.state.mediaContents} handleChangeUrl={this.handleChangeUrl} handleChangeContent={this.handleChangeContent} /> 
 
    })  
 

 
    
 
[...] 
 

 

 
<div> 
 
    { mediaFields } 
 
    <Button onClick={() => this.add() }>Add media field</Button> 
 
    <Button onClick={() => this.remove() }>Remove media field</Button> 
 
</div>

Как вы можете видеть, у меня есть почти такая же функция, и я понимаю, что это не здорово, поэтому я хочу узнать, как я могу это сделать р.

Я хочу сохранить оба значения в одном и том же объекте. Как так:

const mediaContent = [ link1: content1, link2: content2, link3: content3 ]

Надежда кто-то может толкать меня в правильном направлении.

ответ

0

В Javascript массив может быть проиндексирован только числом (это не похоже на PHP).

При этом вы можете иметь оба значения, как вы хотите, в объекте (json).

Таким образом, вы бы что-то вроде:

const mediaContent = { link1: content1, link2: content2, link3: content3 } 

Тогда вам просто нужно обработать ваш объект как массив. Объект не имеет методов pop и concat, но его можно легко достичь, используя Object.Assign для добавления, и Object.keys + уменьшающие функции карты для удаления (фактически обрабатывая ваш объект снова как массив).

Дополнительная подсказка: вы можете удалить переменную i и вместо этого использовать Object.keys (this.state.mediaFields) .length.

add() { 
 
    event.preventDefault(); 
 
    const mediaFields = Object.assign(this.state.mediaFields, MediaInput); 
 
    if (i < 3) { 
 
    this.setState({ mediaFields }); 
 
    i++; 
 
    } else { 
 
    Bert.alert('Only 3 media links are allowed', 'danger'); 
 
    } 
 
}

remove() { 
 
    event.preventDefault(); 
 
    
 
    const mediaFields = Object.keys(this.state.mediaFields) 
 
     .map(k => this.state.mediaFields[k]) 
 
     .pop() 
 
     .reduce((items, curr) => ({ 
 
     ...items, 
 
     curr 
 
     }), {}); 
 
    
 
    this.setState({ mediaFields }); 
 
    i-- 
 
    }

Имейте в виду, что поддержание порядка для добавления и удаления не может работать должным образом.

+0

На самом деле мне просто удалось получить массивы в объекте, используя: «const mediaObject = _.zipObject (mediaUrls, mediaContents);» Но теперь я столкнулся с другой проблемой. Как сопоставить этот массив и использовать оба этих значения. Кажется, что в большинстве случаев используется только одно из этих значений .... – Deelux

+0

'Object.keys (mediaObject) .map (url => {const content = mediaObject [url]}' должен делать трюк –

+0

Я не знаю, я понял, что это не определено. Когда я добавляю эту функцию в константу и пытаюсь войти в нее, что я вернусь "[undefined, undefined]" – Deelux

Смежные вопросы