Что, вероятно, происходит, так это то, что React считает, что между рендерами добавляется только один MyInput
(unemployment-duration
). Таким образом, job-title
никогда не заменяется на unemployment-reason
, и поэтому переопределенные значения меняются местами.
Когда React выполняет diff, он определит, какие компоненты являются новыми и старыми на основе их свойства key
. Если в коде нет такого ключа, он будет генерировать его.
Причина, по которой последний фрагмент кода, который вы предоставляете, работает, потому что React по существу должен изменить иерархию всех элементов в родительском div
, и я считаю, что это вызовет повторную реорганизацию всех детей (именно поэтому это работает). Если бы вы добавили span
внизу, а не в верхнюю часть, иерархия предыдущих элементов не изменилась бы, и эти элементы не будут повторно отображаться (и проблема будет сохраняться).
Вот что говорится в официальной документации React :
Ситуация усложняется, когда дети перетасовываются (как в результатах поиска) или добавляются новые компоненты на перед списком (как в потоках). В тех случаях, когда идентификация и состояние каждого дочернего элемента должны поддерживаться через проходы рендеринга, вы можете однозначно идентифицировать каждого ребенка, назначив ему ключ.
Когда React примиряет детей с ключами, он гарантирует, что любой ребенок с ключом будет переупорядочен (вместо clobbered) или уничтожен (вместо повторного использования).
blockquote>Вы должен иметь возможность исправить это, предоставив уникальный элемент
key
самостоятельно либо родительскомуdiv
, либо всем элементамMyInput
.Например:
render(){ if (this.state.employed) { return (
); } else { return ( ); } }OR
render(){ if (this.state.employed) { return (
); } else { return ( ); } }Теперь, когда React выполняет diff, он увидит, что
divs
отличаются и будут повторно отображать его, включая все его «дети» (1-й пример). Во втором примере diff будет успешным наjob-title
иunemployment-reason
, так как теперь у них разные клавиши.Вы можете, конечно, использовать любые нужные вам клавиши, если они уникальны.
Обновить август 2017
Для лучшего понимания того, как работают клавиши в React, я настоятельно рекомендую прочитать мой ответ на Понимание уникальных ключей в React.js .
Обновление ноября 2017 г.
Это обновление должно было быть опубликовано некоторое время назад, но использование строковых литералов в
ref
теперь устарело. Например, теперьref="job-title"
должен бытьref={(el) => this.jobTitleRef = el}
(например). См. Мой ответ на Предупреждение об изъятии с использованием this.refs для получения дополнительной информации.
StringEscapeUtils.unescapeXml(xml)
( commons-lang , скачать )
Вот простой метод для удаления XML. Он обрабатывает предопределенные сущности XML и десятичные числовые сущности (& amp; #nnnn;). Его изменение для обработки шестнадцатеричных сущностей (& amp; #xhhhh;) должно быть простым.
public static String unescapeXML( final String xml )
{
Pattern xmlEntityRegex = Pattern.compile( "&(#?)([^;]+);" );
//Unfortunately, Matcher requires a StringBuffer instead of a StringBuilder
StringBuffer unescapedOutput = new StringBuffer( xml.length() );
Matcher m = xmlEntityRegex.matcher( xml );
Map<String,String> builtinEntities = null;
String entity;
String hashmark;
String ent;
int code;
while ( m.find() ) {
ent = m.group(2);
hashmark = m.group(1);
if ( (hashmark != null) && (hashmark.length() > 0) ) {
code = Integer.parseInt( ent );
entity = Character.toString( (char) code );
} else {
//must be a non-numerical entity
if ( builtinEntities == null ) {
builtinEntities = buildBuiltinXMLEntityMap();
}
entity = builtinEntities.get( ent );
if ( entity == null ) {
//not a known entity - ignore it
entity = "&" + ent + ';';
}
}
m.appendReplacement( unescapedOutput, entity );
}
m.appendTail( unescapedOutput );
return unescapedOutput.toString();
}
private static Map<String,String> buildBuiltinXMLEntityMap()
{
Map<String,String> entities = new HashMap<String,String>(10);
entities.put( "lt", "<" );
entities.put( "gt", ">" );
entities.put( "amp", "&" );
entities.put( "apos", "'" );
entities.put( "quot", "\"" );
return entities;
}
Вот тот, который я написал за десять минут. Он не использует регулярные выражения, только простые итерации. Я не думаю, что это может быть улучшено, чтобы быть намного быстрее.
public static String unescape(final String text) {
StringBuilder result = new StringBuilder(text.length());
int i = 0;
int n = text.length();
while (i < n) {
char charAt = text.charAt(i);
if (charAt != '&') {
result.append(charAt);
i++;
} else {
if (text.startsWith("&", i)) {
result.append('&');
i += 5;
} else if (text.startsWith("'", i)) {
result.append('\'');
i += 6;
} else if (text.startsWith(""", i)) {
result.append('"');
i += 6;
} else if (text.startsWith("<", i)) {
result.append('<');
i += 4;
} else if (text.startsWith(">", i)) {
result.append('>');
i += 4;
} else i++;
}
}
return result.toString();
}
Если вы работаете с JSP, используйте su: unescapeXml из openutils-elfunctions