Reactjs setState () с именем динамического ключа?

248

РЕДАКТИРОВАТЬ: это дубликат, смотрите здесь

Я не могу найти никаких примеров использования имени динамического ключа при установке состояния. Вот что я хочу сделать:

inputChangeHandler : function (event) {
    this.setState( { event.target.id  : event.target.value } );
},

где event.target.id используется в качестве ключа состояния для обновления. Разве это не возможно в React?

трад
источник
4
Это дубликат любого вопроса, касающегося ключей динамических объектов. Это не является специфическим, чтобы реагировать
Кори Дэниелсон
9
var newstate = {}; newstate [event.target.id] = event.target.id; this.setState (NewState);
Кори Дэниелсон
Спасибо, у меня не было хорошего подхода к использованию объектов в целом.
trad
@trad Я с этой проблемой, но что ты поставил на исходное состояние? Это не имеет значения, верно?
Рафаэль Онофре

Ответы:

280

Благодаря подсказке @ Кори, я использовал это:

inputChangeHandler : function (event) {
    var stateObject = function() {
      returnObj = {};
      returnObj[this.target.id] = this.target.value;
         return returnObj;
    }.bind(event)();

    this.setState( stateObject );    
},

Если вы используете ES6 или транспортер Babel для преобразования вашего кода JSX, вы можете сделать это и с помощью вычисляемых имен свойств :

inputChangeHandler : function (event) {
    this.setState({ [event.target.id]: event.target.value });
    // alternatively using template strings for strings
    // this.setState({ [`key${event.target.id}`]: event.target.value });
}
трад
источник
27
Для этого также есть новый синтаксис, если вы используете bablejs для сборки своего кода. Вы можете использоватьcomputed property names
Кори Дэниелсон
Второй подход вызывает синтаксическую ошибку в браузерах в Windows (IE, Chrome). Кто-нибудь заметил?
Бенджаминз
как заявить?
Муним Хабиб
Спасибо trad, это то, что я искал, чтобы избежать дублирования кода для <Radio />реализации.
Адеш М
6
Если вы устанавливаете состояние, используя вычисляемое имя свойства, как это: this.setState({ [event.target.id]: event.target.value });тогда как бы вы получили доступ к этому состоянию, используя this.state......?
user3574492
142

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

Например:

inputChangeHandler(event) {
  this.setState({ [event.target.name]: event.target.value });
}

Викрам Джит Сингх
источник
7
Что указывают скобки вокруг [event.target.name]? Зачем они нужны?
user798719
1
По сравнению с обычным подходом именовать каждый элемент отдельно, как this.setState ({userName: e.target.value}); Это будет обрабатывать несколько элементов формы в виде массива, и нет необходимости устанавливать каждый отдельный элемент
vikram jeet singh
1
но все же, как я могу получить доступ к этому состоянию таким же образом? как this.state([event.target.name])?
Киранкумар Дафда
1
Я думаю, что MDN веб-документы и этот пост объясняет, почему нам нужны скобки.
Келли
46

Как мне это удалось ...

inputChangeHandler: function(event) {
  var key = event.target.id
  var val = event.target.value
  var obj  = {}
  obj[key] = val
  this.setState(obj)
},
sintaxi
источник
Я сделал то же самое, но проблема заключалась в том, что он все еще не рендерил компонент, и я запустил столб для публикации (включая это: D), и где-то нашел это: this.forceUpdate();чего не должно было случиться с последним React. Давайте посмотрим, в чем проблема позже!
xploreraj
24

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

inputChangeHandler: function ({ target: { id, value }) {
    this.setState({ [id]: value });
},
saulable
источник
10

В цикле с .mapработой, как это:

{
    dataForm.map(({ id, placeholder, type }) => {
        return <Input
            value={this.state.type}
            onChangeText={(text) => this.setState({ [type]: text })}
            placeholder={placeholder}
            key={id} />
    })
}

Обратите внимание на параметр []in type. Надеюсь это поможет :)

Джонатан Масиэль
источник
10

У меня была похожая проблема.

Я хотел установить состояние хранения ключа 2-го уровня в переменной.

например this.setState({permissions[perm.code]: e.target.checked})

Однако это неверный синтаксис.

Я использовал следующий код для достижения этой цели:

this.setState({
  permissions: {
    ...this.state.permissions,
    [perm.code]: e.target.checked
  }
});
Мэтью Холтом
источник
4

С ES6 + вы можете просто сделать [ ${variable}]

Джуджар Сингх
источник
2

Я искал красивое и простое решение, и я нашел это:

this.setState({ [`image${i}`]: image })

Надеюсь это поможет

Catalina
источник
1
this.setState({ [`${event.target.id}`]: event.target.value}, () => {
      console.log("State updated: ", JSON.stringify(this.state[event.target.id]));
    });

Пожалуйста, обратите внимание на символ цитаты.

Javatar
источник
0

Ваше состояние со словарем обновляет один ключ, не теряя другого значения

state = 
{   
    name:"mjpatel"  
    parsedFilter:
    {
      page:2,
      perPage:4,
      totalPages: 50,
    }
}

Решение ниже

 let { parsedFilter } = this.state
 this.setState({
      parsedFilter: {
        ...this.state.parsedFilter,
        page: 5
      }
  });

здесь обновите значение для ключа "страница" значением 5

Маной Патель
источник
-4

Можно использовать синтаксис распространения, что-то вроде этого:

inputChangeHandler : function (event) {
    this.setState( { 
        ...this.state,
        [event.target.id]: event.target.value
    } );
},
станция
источник
7
React сделает слияние объектов за вас, это плохая практика.
Rohmer
1
в основном, если у вас есть какой-то внутренний объект и вы хотите изменить одно свойство для этого внутреннего объекта, вы делаете это следующим образом: this.setState ({selectedItems: {... selectedItems, [item.id]: true}})
Eran Or