Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #21 (permalink)  
Старый 16.07.2021, 13:47
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 5,928

Сообщение от Alexandroppolus Посмотреть сообщение
но ведь сам рендер вызывается однократно, если в коде синхронно поменялось и то и другое и третье, так что не проблема
Ну так ващет нет. Три изменения - три рендера и будет. Если не больше.
__________________
29375, 35
Ответить с цитированием
  #22 (permalink)  
Старый 16.07.2021, 13:49
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 13,321

Сообщение от Alexandroppolus
А уж если такое не поможет - менять массив иммутабельно, то есть вместо test.data.arr.push(newItem) делать
test.data.arr = [...test.data.arr, newItem]
А вот такое сработало!

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)
	    this.data.arr = [...this.data.arr, 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, runInAction } from "mobx"

import test from '../store/test'

function Test() {
	const renderItem = ({ item }) => (
	    <Text>{item.name}</Text>
	)

	return (
	    <View style={styles.container}>
    	    <View style={styles.tab}>
    	        <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,
		color: '#000',
		backgroundColor: '#fff',
		alignItems: 'center',
		justifyContent: 'center',
	},
	tab: {
	    margin: 70
	}
})

export default observer(Test)
Ответить с цитированием
  #23 (permalink)  
Старый 16.07.2021, 14:26
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 902

Сообщение от Aetae
Ну так ващет нет. Три изменения - три рендера и будет. Если не больше.
вот накидал пример.
по кнопке случается все 3 вида изменений - две замены стейта, значение в пропсе, наблюдаемое значение в сторе. Перерендер один - он, похоже, идет следующим микротаском, потому что если store.func() обернуть в микротаск, то уже будет 2 рендера.

в общем, реакт с мобиксом не так уж плохи

import { makeObservable, observable, action } from 'mobx'
import React, { useState } from 'react'
import { observer } from 'mobx-react-lite'

class Store {
  constructor() {
    makeObservable(this)
  }

  @observable a = 1

  @observable b = 2

  @action func() {
    this.a += 1
    this.b += 1
  }
}

const store = new Store()

const Comp: React.FC<{ a: number }> = observer(({ a }) => {
  const [c, setC] = useState(3)
  const [d, setD] = useState(4)
  console.log('*** render Comp ', a, store.b, c, d)

  const handler = () => {
    setC(c + 1)
    setD(d + 1)
    // Promise.resolve().then(() => store.func())
    store.func()
  }

  return (
    <div>
      <div>{`a = ${a}, store.b = ${store.b}, c = ${c}, d = ${d}`}</div>
      <button type="button" onClick={handler}>
        change
      </button>
    </div>
  )
})

export const App: React.FC = observer(() => {
  console.log('*** render App')
  return <Comp a={store.a} />
})
Ответить с цитированием
  #24 (permalink)  
Старый 16.07.2021, 14:33
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 902

Сообщение от ksa
...код.....

Cannot call a class as a function
попробуй заимпортировать так:
import { observer} from 'mobx-react'

ещё поправки, для чистоты эксперимента:

const MobxFlatList = observer(FlatList)
это вынеси наружу из function Test()

const renderItem = ...
тоже вынеси

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

Alexandroppolus, я все это "запишу себе в книжечка"... (с)
Мало ли когда пригодится.

Больше устроил вариант с другим подходом собственно изменения массива.
Ответить с цитированием
Ответ



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

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