16.07.2021, 07:44
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,235
|
|
Сообщение от Alexandroppolus
|
если там массив объектов, который @observable (то есть deep), то slice() вернёт массив отслеживаемых объектов, это ведь поверхностная копия.
|
Мы и по "массиву" проходились фором, каждый элемент делали обычным объектом и вставляли в новый массив.
В консоли все нормально, но тут же ошибка про попытку менять отслеживаемые данные...
Скоро поеду на работу - сделаем примеры, покажу тут.
|
|
16.07.2021, 09:45
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,235
|
|
Ситуация получается более запутанной...
Сделал я тестик простенький и у меня все заработало без всяких предупреждений!
Хранилище
import {makeAutoObservable} from 'mobx'
class Test {
data = {
arr: [
{id: '0', name: 'Item 0'},
{id: '1', name: 'Item 1'},
{id: '2', name: 'Item 2'},
]
}
constructor(props) {
makeAutoObservable(this)
}
add(obj) {
this.data.arr.push(obj)
}
}
export default new Test()
Собственно экран
import React from "react"
import { StyleSheet, Text, View, Button, FlatList } from 'react-native'
import { observer} from 'mobx-react-lite'
import { toJS } from "mobx"
import test from '../store/test'
function Test() {
//console.log(1, test.data.arr)
const arr = toJS(test.data.arr)
//console.log(2, test.data.arr)
const renderItem = ({ item }) => (
<Text>{item.name}</Text>
)
return (
<View style={styles.container}>
<View style={styles.container}>
<Button
title='Add'
onPress={add}
/>
</View>
<FlatList
data={test.data.arr}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</View>
)
function add() {
const l = test.data.arr.length
test.add({
id: l.toString(),
name: 'Item ' + l
})
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
tab: {
margin: 50
}
})
export default observer(Test)
Все рисуется и так нормально... НО!
если убрать
const arr = toJS(test.data.arr)
Перестает работать добавление элементов.
Возвращаю эту строку - работает добавление.
А по предыдущей проблеме - сказал чтобы ребята начали искать у себя проблемы глубже...
|
|
16.07.2021, 10:14
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,235
|
|
Сообщение от ksa
|
сказал чтобы ребята начали искать у себя проблемы глубже...
|
Выяснили следующее...
Было асинхронное чтение данных с сервера. Изменение состояния обернули в runInAction() из mobx и ошибка ушла. FlatList стал отображать данные из хранилища mobx без замечаний.
Но по моему примеру все еще интересно что так влияет на работоспособность кнопки Add в моем примере?
|
|
16.07.2021, 10:45
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
Сообщение от ksa
|
Но по моему примеру все еще интересно что так влияет на работоспособность кнопки Add в моем примере?
|
кнопка Add работает, просто компонент не перерисовывается
без toJS ты читаешь только test.data.arr (и как следствие подписываешься только на изменение test.data.arr), а он не меняется, массив тот же самый, только в него запушили.
вызов toJS(test.data.arr) делает чтение вообще всего, что есть внутри массива, и соответственно подписки будут на все изменения.
и конечно, здесь не самая экономичная схема перерендеров. Что-то поменяли, и перерендеривается всё. Тут надо тоже смотреть по ситуации, как лучше сделать, и разумеется, без toJS
|
|
16.07.2021, 10:47
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
Сообщение от ksa
|
Изменение состояния обернули в runInAction() из mobx и ошибка ушла.
|
а в тестовом примере изменения стейта были внутри сторовского метода add, который по воле makeAutoObservable обернулся в action и получил право менять данные.
|
|
16.07.2021, 11:58
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,235
|
|
Сообщение от Alexandroppolus
|
просто компонент не перерисовывается
|
Вона че...
Сообщение от Alexandroppolus
|
в тестовом примере изменения стейта были внутри сторовского метода add, который по воле makeAutoObservable обернулся в action и получил право менять данные
|
Так вот я и думал что это даст возможность рендеренга FlatList... А оно видал как.
Сообщение от Alexandroppolus
|
Тут надо тоже смотреть по ситуации, как лучше сделать, и разумеется, без toJS
|
И что можно придумать "альтернативного"?
В "простом" Реакте вполне хватало использования "сторных" методов и все перерисовывалось...
А теперь этого мало...
|
|
16.07.2021, 12:34
|
|
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,590
|
|
А потому, что он цепляется через жёпу. Потому что реакт - не расширяем нихрена. Вызовы рендера: стейт - отдельно, пропс - отдельно, нужен стор? - тоже отдельно.
Можешь попробовать энтот твой FlatList в <Observer><FlatList ...></Observer> заключить, но это так - выстрел в небо, загружать сейчас в голову весь контекст как оно там на самом деле работает откровенно лень.)
__________________
29375, 35
|
|
16.07.2021, 13:04
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
Сообщение от Aetae
|
Вызовы рендера: стейт - отдельно, пропс - отдельно, нужен стор? - тоже отдельно.
|
но ведь сам рендер вызывается однократно, если в коде синхронно поменялось и то и другое и третье, так что не проблема
Сообщение от Aetae
|
Можешь попробовать энтот твой FlatList в <Observer><FlatList ...></Observer> заключить
|
не поможет, FlatList от этого не станет обзервером
я бы попробовал так:
const MobxFlatList = observer(FlatList)
и потом юзать MobxFlatList. А уж если такое не поможет - менять массив иммутабельно, то есть вместо test.data.arr.push(newItem) делать test.data.arr = [...test.data.arr, newItem]
ну и там далее ещё кое-где поменять.
использовать в рендере toJS - это антиMobX
|
|
16.07.2021, 13:38
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,235
|
|
Сообщение от Aetae
|
Можешь попробовать энтот твой FlatList в
<Observer><FlatList ...></Observer>
заключить
|
Это первое что мы опробовали...
Не помогает.
Сообщение от Alexandroppolus
|
я бы попробовал так:
const MobxFlatList = observer(FlatList)
|
Ща спробанем!
Сообщение от Alexandroppolus
|
А уж если такое не поможет - менять массив иммутабельно, то есть вместо test.data.arr.push(newItem) делать
test.data.arr = [...test.data.arr, newItem]
|
Опробую и это...
Сообщение от Alexandroppolus
|
использовать в рендере toJS - это антиMobX
|
Это-то понятно...
|
|
16.07.2021, 13:44
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,235
|
|
Сообщение от Alexandroppolus
|
я бы попробовал так:
const MobxFlatList = observer(FlatList)
|
Сделал так...
import React from "react"
import { StyleSheet, Text, View, Button, FlatList } from 'react-native'
import { observer} from 'mobx-react-lite'
import { toJS, runInAction } from "mobx"
import test from '../store/test'
function Test() {
//const arr = toJS(test.data.arr)
const renderItem = ({ item }) => (
<Text>{item.name}</Text>
)
const MobxFlatList = observer(FlatList)
return (
<View style={styles.container}>
<View style={styles.tab}>
<Button
title='Add'
onPress={add}
/>
</View>
<MobxFlatList
data={test.data.arr}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</View>
)
function add() {
const l = test.data.arr.length
test.add({
id: l.toString(),
name: 'Item ' + l
})
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
color: '#000',
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
tab: {
margin: 70
}
})
export default observer(Test)
Ошибка
Cannot call a class as a function
|
|
|
|