#javascript #reactjs #meteor
#javascript #reactjs #метеор
Вопрос:
У меня есть одно состояние внутри моего компонента React, которое имеет такую структуру {a: {x: 0}, b: {x:0}}
. Во время работы мне нужно запустить несколько запросов к серверу, чтобы запросить данные для обновления состояния, и это необходимо обновить в состоянии. Поскольку номер записи в базе данных довольно большой, мне приходится запускать несколько раз
Если мне это нравится
request_data(e) {
['a', 'b'].forEach((k) => {
// do not mutate the state directly
let new_state = _.extend({}, state);
request(params, (err, res) => {
// set result to the new_state
new_state = res;
// update the original state
this.setState(newState);
})
});
}
внутри обратного вызова второй запрос не будет иметь данных первого запроса в тот момент, когда он запрашивает и обновляет исходное состояние пустым значением для первой ветви структуры состояния.
Одним из простых решений является прямое обновление исходного состояния, но я не думаю, что это хорошая идея. Я планирую интегрировать redux
позже, но на данный момент, поскольку текущая база кода довольно большая, лучше выполнять постепенную миграцию. Однако я не хочу напрямую изменять исходное состояние, поскольку это не redux
так. Есть предложения по преодолению этой проблемы?
Комментарии:
1. Что вы делаете внутри метода жизненного цикла компонента React? Где находится этот код?
2. В данный момент я обновляю свое приложение из Blaze до React, и часть его все еще находится внутри Blaze. Фактический код довольно сложный
ReactiveVar
, в том числе и для meteor, но предположим, что этот код находится внутри компонента React. Я не вижу никакой разницы, поскольку это общая проблема объединения нескольких копий состояния во время обратных вызовов
Ответ №1:
Я предполагаю, что, судя по тому, как написан ваш код, вы используете классы es6 для своего компонента? В таком случае, надеюсь, этот лакомый кусочек поможет:
import React from 'react'
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
foo:'bar'
}
}
request_data = (e) => {
['a', 'b'].forEach((k) => {
// do not mutate the state directly
let new_state = _.extend({}, state);
request(params, (err, res) => {
// set result to the new_state
// update the original state
this.setState(foo:res.foo)
})
});
}
render() {
return (
// component code here
)
}
}
export default MyComponent
Обратите внимание, что я использую функцию со стрелкой для части request_data…это делается для того, чтобы избежать необходимости привязывать функцию к this
переменной внутри конструктора.
Обновить:
Я все еще не совсем уверен, что понимаю, с какой проблемой вы столкнулись здесь … но если вы не хотите использовать redux прямо сейчас, вы можете использовать метод компонента контейнера. По сути, основная задача вашего компонента контейнера — управлять данными и ничего не делать, кроме как передавать его обновленное состояние дочернему компоненту в качестве реквизита. Что-то вроде этого:
class MyComponentContainer extends React.Component {
constructor(props) {
super(props)
this.state = {
a: {
x: 0
},
b: {
x:0
}
}
}
componentWillMount() {
['a', 'b'].forEach((k) => {
request(params, (err, res) => {
this.setState({
a: res.a,
b: res.b
});
})
});
}
render() {
return (
<MyComponent data={this.state} />
)
}
}
class MyComponent extends React.Component {
constructor (props) {
super(props)
}
render() {
return (
<div>
{/* display stuff here */}
</div>
)
}
}
export default MyComponentContainer
Комментарии:
1. Пожалуйста, внимательно прочитайте мой вопрос. Я знаю, что могу напрямую изменять исходное состояние, но я не думаю, что это хорошая идея. Поскольку позже я мог бы интегрироваться с
redux
, и я не хочу снова менять свой код с помощьюimmutablejs
2. Использование setState не изменяет состояние напрямую. Когда вы начнете использовать redux, вы сможете создавать новые объекты состояния либо с помощью Object.assign, либо _.extend, либо с помощью оператора распространения, как вам заблагорассудится. В этом случае вы находитесь внутри компонента, который предоставляет вам метод setState и не изменяет состояние напрямую. Это метод, который компоненты React предоставили для обновления состояния.
3. если вы говорите об этом.state = {} в конструкторе, это не обновление состояния, а установка его начального значения. Мы говорим здесь о состоянии компонента, верно?
4. Привет, Майк, я пытаюсь использовать
new_state
внутреннюю функцию для вводаthis.setState
. Позже я использую визуализациюredux
, код будет примерно таким в редукторах:new_state = Object.assign({}, state); return new_state;
, и если мой текущий код уже справляется сimmutablejs
проблемой, мне не нужно думать о логике позже5. Итак, вы хотите изменить состояние напрямую? На мой взгляд, я бы все равно использовал redux здесь, поскольку вы все равно планируете использовать его в будущем, и просто используйте redux для компонентов React, на которые вы переходите. Вы можете постепенно создавать новые редукторы по мере необходимости, и вы можете использовать redux только для тех компонентов, которые вам нужны. Другими словами, вы все равно можете использовать redux, даже если вы постепенно переходите.