Skip to content

Commit

Permalink
fix(useListTransition): updating an array of objects often leads to a…
Browse files Browse the repository at this point in the history
… duplicate div in the DOM (#2)

close #2
  • Loading branch information
Daydreamer-riri committed Jul 31, 2024
1 parent 2e73e79 commit 529236a
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 19 deletions.
55 changes: 43 additions & 12 deletions playground/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,57 @@
import { useState } from 'react'
import { SwitchTransition } from 'transition-hooks'
import { useListTransition } from 'transition-hooks'
// import { startViewTransition } from 'transition-hooks/viewTransition'

export function App() {
const [show, setShow] = useState(false)
const [list, setList] = useState([
{ id: 1, text: '1' },
{ id: 2, text: '2' },
])

const { transitionList } = useListTransition(list, {
timeout: 1000,
keyExtractor: i => i.id,
})

const updateLastItem = () => {
const newList = [...list]
newList[newList.length - 2] = {
id: newList[newList.length - 2].id,
text: `${newList[newList.length - 2].text}test`,
}
setList(newList)
}

const addItem = () => {
setList(l => [...l, { id: l.length + 1, text: (l.length + 1).toString() }])
}

return (
<div>
<SwitchTransition state={show}>
{(state, { status }) => {
<div style={{ display: 'flex', gap: 4, marginBottom: 8 }}>
<button onClick={addItem}>add</button>
<button onClick={updateLastItem}>update last item</button>
</div>
<ul>
{transitionList((item, { key, simpleStatus }) => {
return (
<div
<li
style={{
transition: 'opacity 0.3s',
opacity: status === 'entering' || status === 'entered' ? 1 : 0,
position: simpleStatus === 'exit' ? 'absolute' : 'relative',
opacity: simpleStatus === 'enter' ? 1 : 0,
transform:
simpleStatus === 'enter'
? 'translateX(0)'
: 'translateX(20px)',
transition: 'all .6s',
// viewTransitionName: simpleStatus === 'enter' ? `transition-list-${key}` : '',
}}
>
Hello Word {state ? 'true' : 'false'}
</div>
- {item.text}
</li>
)
}}
</SwitchTransition>
<button onClick={() => setShow(!show)}>toggle</button>
})}
</ul>
</div>
)
}
48 changes: 41 additions & 7 deletions src/hooks/useListTransition.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,43 @@ export function useListTransition<Item>(list: Array<Item>, options?: ListTransit

useEffect(
() => {
// const hasChanged = listState.length !== list.length
// || (hasCustomKeyExtractor && list.some((item, index) => keyExtractor(item) !== listState[index].key))
// console.log('🚀 ~ hasChanged:', hasChanged)
// if (!hasChanged)
// return

const newItemsWithIndex: Array<ItemWithKey<Item>> = []
const updatedItemsWithIndex: Array<ItemWithKey<Item>> = []

list.forEach((item, index) => {
if (listState.every(itemState => itemState.item !== item))
newItemsWithIndex.push({ item, index })
if (listState.every(itemState => itemState.item !== item)) {
if (hasCustomKeyExtractor && listState.some(itemState => keyExtractor(item) === itemState.key))
updatedItemsWithIndex.push({ item, index })
else
newItemsWithIndex.push({ item, index })
}
})

if (updatedItemsWithIndex.length > 0) {
viewTransition(() => {
setListState(prevListState => {
const newListState = [...prevListState]
updatedItemsWithIndex.forEach(({ item }) => {
const targetIndex = newListState.findIndex(itemState => itemState.key === keyExtractor(item))
if (targetIndex > -1) {
const originItem = newListState[targetIndex]
newListState[targetIndex] = {
...originItem,
item,
}
}
})
return newListState
})
})
}

// 1 add new items into list state
if (newItemsWithIndex.length > 0) {
viewTransition(() => {
Expand Down Expand Up @@ -138,11 +168,15 @@ export function useListTransition<Item>(list: Array<Item>, options?: ListTransit
) {
viewTransition(() => {
setListState(
list.map(item => ({
item,
key: keyExtractor(item),
...getState(STATUS.entered),
})),
list.map(item => {
const key = keyExtractor(item)
const originItem = listState.find(itemState => itemState.key === key)
return {
...(originItem || getState(STATUS.entered)),
item,
key,
}
}),
)
})
}
Expand Down

0 comments on commit 529236a

Please sign in to comment.