Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #11 (permalink)  
Старый 16.07.2021, 07:44
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,123

Сообщение от Alexandroppolus
если там массив объектов, который @observable (то есть deep), то slice() вернёт массив отслеживаемых объектов, это ведь поверхностная копия.
Мы и по "массиву" проходились фором, каждый элемент делали обычным объектом и вставляли в новый массив.
В консоли все нормально, но тут же ошибка про попытку менять отслеживаемые данные...
Скоро поеду на работу - сделаем примеры, покажу тут.
Ответить с цитированием
  #12 (permalink)  
Старый 16.07.2021, 09:45
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,123

Ситуация получается более запутанной...
Сделал я тестик простенький и у меня все заработало без всяких предупреждений!

Хранилище
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)

Перестает работать добавление элементов.
Возвращаю эту строку - работает добавление.

А по предыдущей проблеме - сказал чтобы ребята начали искать у себя проблемы глубже...
Ответить с цитированием
  #13 (permalink)  
Старый 16.07.2021, 10:14
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,123

Сообщение от ksa
сказал чтобы ребята начали искать у себя проблемы глубже...
Выяснили следующее...
Было асинхронное чтение данных с сервера. Изменение состояния обернули в runInAction() из mobx и ошибка ушла. FlatList стал отображать данные из хранилища mobx без замечаний.

Но по моему примеру все еще интересно что так влияет на работоспособность кнопки Add в моем примере?
Ответить с цитированием
  #14 (permalink)  
Старый 16.07.2021, 10:45
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,005

Сообщение от ksa
Но по моему примеру все еще интересно что так влияет на работоспособность кнопки Add в моем примере?
кнопка Add работает, просто компонент не перерисовывается

без toJS ты читаешь только test.data.arr (и как следствие подписываешься только на изменение test.data.arr), а он не меняется, массив тот же самый, только в него запушили.

вызов toJS(test.data.arr) делает чтение вообще всего, что есть внутри массива, и соответственно подписки будут на все изменения.

и конечно, здесь не самая экономичная схема перерендеров. Что-то поменяли, и перерендеривается всё. Тут надо тоже смотреть по ситуации, как лучше сделать, и разумеется, без toJS
Ответить с цитированием
  #15 (permalink)  
Старый 16.07.2021, 10:47
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,005

Сообщение от ksa
Изменение состояния обернули в runInAction() из mobx и ошибка ушла.
а в тестовом примере изменения стейта были внутри сторовского метода add, который по воле makeAutoObservable обернулся в action и получил право менять данные.
Ответить с цитированием
  #16 (permalink)  
Старый 16.07.2021, 11:58
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,123

Сообщение от Alexandroppolus
просто компонент не перерисовывается
Вона че...

Сообщение от Alexandroppolus
в тестовом примере изменения стейта были внутри сторовского метода add, который по воле makeAutoObservable обернулся в action и получил право менять данные
Так вот я и думал что это даст возможность рендеренга FlatList... А оно видал как.
Сообщение от Alexandroppolus
Тут надо тоже смотреть по ситуации, как лучше сделать, и разумеется, без toJS
И что можно придумать "альтернативного"?
В "простом" Реакте вполне хватало использования "сторных" методов и все перерисовывалось...
А теперь этого мало...
Ответить с цитированием
  #17 (permalink)  
Старый 16.07.2021, 12:34
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,492

А потому, что он цепляется через жёпу. Потому что реакт - не расширяем нихрена. Вызовы рендера: стейт - отдельно, пропс - отдельно, нужен стор? - тоже отдельно.

Можешь попробовать энтот твой FlatList в <Observer><FlatList ...></Observer> заключить, но это так - выстрел в небо, загружать сейчас в голову весь контекст как оно там на самом деле работает откровенно лень.)
__________________
29375, 35
Ответить с цитированием
  #18 (permalink)  
Старый 16.07.2021, 13:04
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,005

Сообщение от 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
Ответить с цитированием
  #19 (permalink)  
Старый 16.07.2021, 13:38
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,123

Сообщение от 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
Это-то понятно...
Ответить с цитированием
  #20 (permalink)  
Старый 16.07.2021, 13:44
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,123

Сообщение от 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
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск