У меня есть компонент, который включает форму проверки для пользователя. Этот компонент запускает запрос graphql при монтировании. В компоненте Verification мне нужно использовать данные из запроса graphql, чтобы установить состояние, чтобы я мог использовать его для обновления любых значений, а затем отправить их с формой. С тех пор я узнал о getDerivedStateFromProps, и он работает над заполнением нового состояния на основе этих данных. Но данные недоступны в DOM. Как будто render вызывается раньше getDerivedStateFromProps.
Вот компонент:
class Verification extends React.Component {
constructor(props) {
super(props);
this.state = {
company: {
legalName: ''
},
openCorporatesCompany: {}
};
}
handleLegalNameChange = (legalName) => {
let company = _.cloneDeep(this.state.company);
company.legalName = legalName;
this.setState({
company
})
};
static getDerivedStateFromProps(next, prev) {
let newState = _.cloneDeep(prev);
let {openCorporates: {getEntityAttribute}} = next;
if (getEntityAttribute && getEntityAttribute.value) {
let openCorporatesCompany = JSON.parse(getEntityAttribute.value);
let company = _.cloneDeep(newState.company);
company.legalName = openCorporatesCompany.name;
newState.openCorporatesCompany = openCorporatesCompany;
newState.company = company;
return newState;
}
return null;
}
render() {
console.info(this.state);
return (
<Input
label='Legal Name'
placeholder='Legal entity name...'
type='text'
subtext='Use the name your customers or clients will recognize'
onChange = {this.handleLegalNameChange}
value = {this.state.legalName}
/>
);
}
}
export const VerificationContainer = compose(
connect(mapStateToProps, mapDispatchToProps)
graphql(GetEntityAttributeQuery, {
name: "openCorporates",
options: (props) => ({
variables: {
entityId: props.currentEntity.id,
type: EntityAttributes.TypeOpenCorporates
}
})
})
)(Verification);
Консольный вывод console.info(this.state) в render выглядит так:
Как видите, поле обновляется в состоянии в company.legalName. Но он никогда не заполняется в поле ввода:
Почему вход не обновляется с новым состоянием? Как будто рендер вызывается до getDerivedStateFromProps.





Я знаю вашу борьбу с реакцией и обновлением компонентов, но полагаю, что нет никаких доказательств, чтобы избавиться от этого; 80% Думаю, вам стоит попробовать любой из различных методов жизненного цикла. Раньше был componentWillReceiveProps для асинхронных вызовов, но поскольку он был помечен как небезопасный (я думаю), вы должны попробовать getDerivedStateFromProps (реквизиты, состояние)
getDerivedStateFromProps(props, state) {
console.info("*************** PROPS:", props);
let { openCorporates: { getEntityAttribute } } = props;
if (getEntityAttribute && getEntityAttribute.value) {
let openCorporatesCompany = JSON.parse(getEntityAttribute.value);
let company = _.cloneDeep(this.state.company);
company.legalName = openCorporatesCompany.name;
this.setState({
openCorporatesCompany,
company
})
}
}
Учтите, что я не запускал сниппет.
лол извини, добавь "статика" в подпись, э.и. static getDerivedStateFromProps (реквизиты, состояние) {...
Как мне успешно использовать этот метод? Он говорит, что мне нужно вернуть объект. Передан ли объект state, объект this.state из компонента? Могу ли я просто изменить этот объект, а затем вернуть его как новое состояние?
извините, я пока не использую реакцию, но по сути вам следует сравнить аргументы, в данном случае next и prev, для значения if (next.openCorporates.value! == prev.openCorporates.value) {return {openCorporates: next .openCorporates}; } else return null; как в этом посте
Откуда берутся следующие и предыдущие? В сигнатуре метода есть только реквизиты и состояние. Кроме того, это работает примерно в половине случаев. Если я распечатываю this.state в функции рендеринга, он каждый раз показывает данные. Но иногда компоненты на странице не имеют данных. Это как если бы рендеринг этого дочернего компонента вызывается перед getDerivedStateFromProps из родительского компонента.
@JonStevens следующий и предыдущий - просто удобные имена. В моем примере я скопировал подпись из документации. При реализации метода вы переходите из одного состояния (предыдущее) в другое состояние (следующее), поэтому вам следует соответственно сравнить и вернуться; обычно следующее состояние - желаемое. Если в нем отсутствовали поля, возможно, поэтому. Итак, консоль регистрирует как следующий, так и предыдущий и создает свой объект (например, newState). Надеюсь, это поможет
Тот же результат. По-прежнему иногда обновляет DOM только этими полями данных.
Можете ли вы использовать фрагмент того, как сейчас выглядят файлы?
Какой сниппет вы ищете?
тот, который не отображает данные должным образом, в этом случае класс, содержащий getDerivedStateFromProps ...
Я обновил свой вопрос, так как считаю, что это новая проблема.
извините за это, похоже, вы должны вызывать componentDidUpdate () после каждого getDerivedStateFromProps, если вы хотите выполнить изменения состояния. Я обновил ваш код
Это закончилось тем, что помогло @ Charlie:
static getDerivedStateFromProps(props, state) {
let newState = _.cloneDeep(state);
let { openCorporates: { getEntityAttribute } } = props;
if (getEntityAttribute && getEntityAttribute.value) {
let openCorporatesCompany = JSON.parse(getEntityAttribute.value);
let company = _.cloneDeep(newState.company);
company.legalName = openCorporatesCompany.name;
newState.openCorporatesCompany = openCorporatesCompany;
newState.company = company;
}
return newState;
}
Я получаю эту ошибку при добавлении:
Warning: Verification: getDerivedStateFromProps() is defined as an instance method and will be ignored. Instead, declare it as a static method.