search

Home  >  Q&A  >  body text

Cannot rewrite the title as it is already explicit and clear

<p>I'm using Flashlist in React Native and I'm using the <code>useCallback</code> hook in my <code>renderItem</code> function. In my component I have a state (an array) called <code>todos</code> and when I log <code>todos.length</code> I only get the initial state value 0. Why is this happening and how do I fix it? </p> <pre class="brush:php;toolbar:false;">export default function MyComponent() { // Some code has been omitted for brevity. const [todos, setTodos] = useState<string[]>([]); const renderItem = useCallback( ({ item }: ListRenderItemInfo<Todo>) => ( <TouchableOpacity style={{ height: 50 }} onPress={() => { console.log(todos.length); // Always log 0. if (todos.length >= 10) return; setTodos((curr) => [item.name, ...curr]); }} > <Heading color={"black"}>{item.name}</Heading> </TouchableOpacity> ), [] ); return ( <FlashList<Todo> data={data?.todos as Todo[]} estimatedItemSize={50} renderItem={renderItem} keyExtractor={(_, idx) => idx.toString()} /> ); }</pre> <p>Note: I tried passing both <code>todos</code> and <code>todos.length</code> as dependencies to <code>useCallback</code> but the result was the same of. </p> <p>Happy to answer any questions. </p>
P粉253518620P粉253518620510 days ago441

reply all(1)I'll reply

  • P粉805922437

    P粉8059224372023-08-16 15:36:35

    const [todos, setTodos] = useState<string[]>([]);

    and

    const renderItem = useCallback(
      () => {
        //todo's here is a closure, it will not update
        //a dependency of [] means, just run once.
      },
      []
    );

    This is a common problem because it's not obvious. Because this happens often, setState has a callback version. In your code you are actually using it to set the state, but you also need to use it to get the current state for a maximum of 10 checks.

    So a simple solution is to put the length check in the callback function of useState.

    setTodos((curr) => curr.length >= 10 ? curr : [item.name, ...curr]);

    In the above code, if the current length is greater than or equal to 10, only the current status is returned, otherwise a new item is added.

    Another option, of course, is to add todos to useCallback's state, but why this doesn't work in FlashList, not sure.

    A better option is to extract Item as another child component. There are other benefits to doing this, such as more composability, code sharing, and most importantly, performance.

    reply
    0
  • Cancelreply