react-nativereact-hooksuse-stategql

How to sort Array data in FlatList?


I put data to useState in order that whenever data changes, UI changes.

  const [state, setState] = useState();

with this data, I run FlatList. (see data part)

    <FlatList
      ref={flatListRef}
      contentContainerStyle={{
        paddingBottom: 20,
      }}
      keyboardDismissMode={true}
      showsVerticalScrollIndicator={false}
      data={state}
      keyExtractor={(comment) => "" + comment.id}
      renderItem={renderComment}
    />

And I want to sort this data by createdAt which is date.

my data which is in state is Array composing of objects.

Array [
  Object {
    "__typename": "Comment",
    "createdAt": "1645612616365",
    "id": 434,
    "isMine": true,
    "payload": "가",
    "user": Object {
      "__typename": "User",
      "avatar": "https://chungchunonuploads.s3.amazonaws.com/avatars/1-1642681327283-%E1%84%80%E1%85%B5%E1%86%B7%E1%84%86%E1%85%B5%E1%84%89%E1%85%AE%E1%86%A8.jpeg",
      "username": "김미숙",
    },
  },
  Object {
    "__typename": "Comment",
    "createdAt": "1645589527805",
    "id": 431,
    "isMine": true,
    "payload": "음",
    "user": Object {
      "__typename": "User",
      "avatar": "https://chungchunonuploads.s3.amazonaws.com/avatars/1-1642681327283-%E1%84%80%E1%85%B5%E1%86%B7%E1%84%86%E1%85%B5%E1%84%89%E1%85%AE%E1%86%A8.jpeg",
      "username": "김미숙",
    },
  },
]

As I searched the way of sorting Array, it advised me to use sort.

So I made the function like below.

  const sortedState = state.sort(function (a, b) {
    parseInt(a.createdAt) - parseInt(b.createdAt) > 0;
  });

My plan was to put this sortedSate in FlatList.

    <FlatList
      data={sortedState}
    />

However, I've faced two error message.

1) Attempted to assign readonly property.

Probably it is because state is declared with const. So I can't sort (change) it..

2) undefined is not an object (evaluating 'state.sort')

I don't know why, but it seems I can't use sort method.

Please help me.

+ when I call setState.

when UI mounts first.

  useEffect(() => {
    setState(updatePhoto?.seePhoto?.comments);
    register("comments", {
      required: true,
    });
  }, [state, updatePhoto, register]);

when I edit comment.

  const updateEditComment = (cache, result) => {
    const {
      data: {
        editComment: { error, ok, id },
      },
    } = result;
    if (ok) {
      refetch();
      setState(updatePhoto);
      textRef.current.clear();
    }
  };
  const onEditValid = async ({ comments }) => {
    const commentId = await AsyncStorage.getItem("@commentId");
    await editCommentMutation({
      variables: {
        id: parseInt(commentId),
        payload: comments,
      },
      update: updateEditComment,
    });
  };

Solution

  • You could sort the data before you render it in the FlatList.

    I've refactored your sort function to

    const getSortedState = (data) => data.sort((a, b) => parseInt(a.createdAt) - parseInt(b.createdAt));
    
    const sortedItems = useMemo(() => {
      if(state) {
        return getSortedState(state);
      }
    
      return state;
    }, [state]);
    
    <FlatList
      data={sortedItems}
    />
    

    Example Snack.