У меня есть MaterialUI диалог , в котором есть несколько текстовых полей, раскрывающихся списков и других вещей. Некоторые из этих элементов должны быть установлены на определенное значение при каждом открытии или повторном открытии диалога. Другие элементы не могут быть загружены, пока не будут выполнены определенные условия (например, загружены пользовательские данные).
Для «сброса» я использую функцию onEnter. Но функция onEnter не запускается до тех пор, пока не введет (дух!) ... но сама функция рендеринга все еще работает - это означает, что любая логика или доступ к переменным javascript в JSX все равно будут происходить. Это оставляет функцию «onEnter» плохо оборудованной, чтобы быть тем местом, которое я настроил и инициализировал мой диалог.
Я также не могу использовать конструктор для установки / сброса этого начального состояния, так как данные мне нужныКонструкция состояния может быть недоступна во время загрузки конструктора (после запуска приложения). Теперь я мог бы усложнить мой JSX в своей функции рендеринга и сделать условия для каждой точки данных ... но это много накладных расходов на то, что перерисовывается каждый раз, когда приложение что-то меняет. (Диалоговые окна пользовательского интерфейса материала запускают всю функцию визуализации, даже если для параметра 'open' установлено значение false).
Каков наилучший способ справиться с инициализацией значений для диалогового окна пользовательского интерфейса материала?
Здесь приведен пример с очень тупыми данными (в реальной жизни представьте, что getInitialState - гораздо более сложная, медленная и потенциально асинхронная / сетевая функция) - давайте представим, что пользовательский объект недоступен в приложении. в начале и на самом деле некоторые данные извлекаются или вводятся задолго до запуска приложения. Этот код завершается ошибкой, потому что «пользователь» не определен при первом рендеринге (что происходит ДО запуска onEnter).
constructor(props) {
super(props);
}
getInitialState = () => {
return {
user: {username: "John Doe"}
}
}
onEnter = () => {
this.setState(this.getInitialState())
}
render() {
const { dialogVisibility } = this.props;
return (
<Dialog open={dialogVisibility} onEnter={this.onEnter}>
<DialogTitle>
Hi, {this.state.user.username}
</DialogTitle>
</Dialog> );
}
Мой первый инстинкт был в том, чтобы поместить в состояние переменную «isInitialized» и позволить только рендерингуверните диалог, если «isInitialized» имеет значение true, например:
constructor(props) {
super(props);
this.state = {
isInitialized: false
};
}
getInitialState = () => {
return {
user: {username: "John Doe"}
}
}
onEnter = () => {
this.setState(this.getInitialState(),
() => this.setState({isInitialized:true})
);
}
render() {
const { dialogVisibility } = this.props;
if(!this.state.isInitialized) {
return null;
}
return (
<Dialog open={dialogVisibility} onEnter={this.onEnter}>
<DialogTitle>
Hi, {this.state.user.username}
</DialogTitle>
</Dialog> );
}
Как я уверен, вы знаете ... это не сработало, так как мы никогда не возвращаем диалог, чтобы запуститьonEnter
событие, которое, в свою очередь, запускает функцию onEnter
и фактически инициализирует данные. Я попытался изменить условное выражение !this.state.inInitialized
на это:
if(!this.state.isInitialized) {
this.onEnter();
return null;
}
, и это работает ... но это дает мне предупреждение во время выполнения: Warning: Cannot update during an existing state transition (such as within
рендер ). Render methods should be a pure function of props and state.
ЭтоЯ много читал, в частности, этот вопрос: Вызов setState при рендеринге недопустим , что действительно привело к тому, что я не должен просто игнорировать это предупреждение. Кроме того, этот метод приводит к тому, что вся логика, содержащаяся в возвращаемом JSX, по-прежнему возникает ... даже когда диалог не "открыт". Добавьте несколько сложных диалогов, и это снизит производительность.
Конечно, есть «правильный» способ сделать это. Помогите? Мысли?