简体   繁体   中英

How to re-render changes in array without useState hook (react-native)

I'm new to react-native and react at all. So i decided to start with simple todo app, but stuck with problem. I moved FlatList, RenderItem method and other methods to deal with tasks list into standalone component. This component imports to HomeScreen, which also store array with all task (this array passes to ItemList as prop). Everything work as i expect, task's view updates if state changes, there deleting from list. But if i want to add task parameters passing by react navigation from another screen to HomeScreen.

tl;dr: array stores in 1st component and this array passes to 2nd component, how to update array and re-render changes.

ItemList.jsx:

import React, { useState } from 'react'
import { FlatList } from 'react-native-gesture-handler'
import { Text } from 'react-native'

import Item from './Item'

const ItemList = (props) => {

  const [taskList, setTaskList] = useState([...props.list])

  const itemRender = ({ item }) => {

    // checkbox handler function
    const checkBoxHandler = (isChecked) => {
      // set Task's isDone state
      let elem = taskList.find(x => x.id === item.id)
      elem.isDone = isChecked

      // removing & pushing elem
      let _taskList = taskList.filter(x => x.id !== elem.id)
      isChecked ? _taskList.push(elem) : _taskList.unshift(elem)
      console.debug(_taskList)

      // call hook
      setTaskList(_taskList)
    }

    // function to count time until deadline
    // and return Text element
    const calculateDeadline = () => {
      var deltaTime = item.expireDate - new Date()
      var deltaDays = Math.ceil(deltaTime / (1000 * 60 * 60 * 24))
      if (!item.isDone) {
        if (0 < deltaDays && deltaDays <= 7)
          return <Text>Deadline in {deltaDays} days</Text>
        else if (deltaDays == 0)
          return <Text>Deadline today!</Text>
        else if (deltaDays < 0)
          return <Text style={{ color: 'red' }}>Overdue</Text>
      }

      return null
    }

    const deleteHandler = () => {
      let _taskList = taskList.filter(x => x.id !== item.id)
      console.debug(_taskList)
      setTaskList(_taskList)
    }


    return (
      <Item
        title={item.title}
        desc={item.desc}
        checkBoxHandler={checkBoxHandler}
        calculateDeadline={calculateDeadline}
        deleteHandler={deleteHandler}
        isDone={item.isDone}
      />
    )
  }

  const onRefresh = () => {
    setTaskList(taskList)

  }

  return (
    <FlatList
      data={taskList}
      renderItem={itemRender}
      keyExtractor={item => item.id}
      onRefresh={onRefresh}
    />
  )
}

export default ItemList

HomeScreen.jsx:

import React, { useEffect } from 'react'
import {
  SafeAreaView,
  StyleSheet,
  StatusBar
} from 'react-native'

import Task from '../Components/modelItem'
import ItemList from '../Components/ItemList'
import FloatButton from '../Components/FloatButton'

const HomeScreen = ({ navigation, route }) => {

  const taskList = [
    new Task(1, 'example', 'some example task', new Date(),
      new Date("2021-10-21")),
    new Task(2, 'RN TODO', 'create todo app', new Date(),
      new Date("2021-11-18")),
    new Task(3, 'something', 'do something', new Date(),
      new Date("2021-11-25")),
  ]

  console.log(route.params)

  useEffect(() => {
    if (route.params?.description) {
      console.log('useEffect:')
      console.log(route.params)
      taskList.push(new Task(null, 'test task', route.params.description,
        route.params.creationDate, route.params.expireDate))
    }
  }, [route.params?.description])


  return (
    <SafeAreaView style={styles}>
      <ItemList
        list={taskList}
      />
      <FloatButton onPress={() => navigation.navigate('AddNewTask')} />
    </SafeAreaView>
  )
}

const styles = StyleSheet.create({
  flex: 1,
  marginTop: StatusBar.currentHeight || 0,
})

export default HomeScreen

taskList.push won't cause an rerender.

Your tasklist should be managed by useState.

Change:

  const taskList = [
    new Task(1, 'example', 'some example task', new Date(),
      new Date("2021-10-21")),
    new Task(2, 'RN TODO', 'create todo app', new Date(),
      new Date("2021-11-18")),
    new Task(3, 'something', 'do something', new Date(),
      new Date("2021-11-25")),
  ]

To:

const [taskList, setTaskList] = useState([
    new Task(1, 'example', 'some example task', new Date(),
      new Date("2021-10-21")),
    new Task(2, 'RN TODO', 'create todo app', new Date(),
      new Date("2021-11-18")),
    new Task(3, 'something', 'do something', new Date(),
      new Date("2021-11-25")),
  ])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM