Search code examples
javascriptreactjsfirebasegoogle-cloud-firestoremui-datatable

How do I pass the text data from firestore inside the expandable row and get the document ID to be passed inside the setState?


In firestore, I have this fields title, createdDate, and text. How do I display the fields title and createdDate in the mui-datatable. The text would then be displayed inside the expanded row. How can I do this?

This is what the data looks like if I'll console.log the blogs: enter image description here

const columns = ["Title", "Created Date"];
const [blogs, setBlogs] = useState([]);

 useEffect(() => {
const unsubscribe = firestore
  .collection("blogs")
  .onSnapshot((snapshot) => {
    const arr = [];
    snapshot.forEach((doc) => {
      const data = doc.data();
      arr.push({
        text: parse(data.text),
        Title: data.title,
        "Created Date": new Date(
          data.createdDate.seconds * 1000
        ).toDateString(),
      });
    });
    setBlogs(arr);
    setIsLoading(true);
  });

    return () => {
      unsubscribe();
    };
  }, []);

  const options = {
    filter: true,
    expandableRows: true,
    renderExpandableRow: (rowData, rowMeta) => {
      console.log(); //how do I render the `text` here from firestore?
    },

  };

Inside the return: I tried putting the blogs inside the data but it doesn't work. No data is showing.

 <MUIDataTable
    title={"List"}
    columns={columns}
    data={blogs}
    options={options}
  />

Solution

  • Just move your setBlogs inside the onSnapshot listener like here:

    useEffect(() => {
      const unsubscribe = firestore
        .collection("blogs")
        .onSnapshot((snapshot) => {
          const arr = [];
          snapshot.forEach((doc) => {
            const data = doc.data();
            arr.push({
              text: parse(data.text),
              Title: data.title,
              "Created Date": new Date(data.createdDate.seconds * 1000).toDateString(),
            });
            setBlogs(arr);
          });
        
          setIsLoading(true);
      });
    
      return () => {
        unsubscribe();
      };
    }, []);
    

    If it's outside of the onSnapshot listener you would always set the blogs as empty array because the setBlogs would be executed before the onSnapshot listener is fired.

    This is they way you can redner and expandable row:

    import MUIDataTable, {ExpandButton} from "../../src/";
    import TableRow from "@material-ui/core/TableRow";
    import TableCell from "@material-ui/core/TableCell";
    
     const options = {
          filter: true,
          filterType: 'dropdown',
          responsive: 'standard',
          expandableRows: true,
          expandableRowsHeader: false,
          expandableRowsOnClick: true,
          isRowExpandable: (dataIndex, expandedRows) => {
            if (dataIndex === 3 || dataIndex === 4) return false;
    
            // Prevent expand/collapse of any row if there are 4 rows expanded already (but allow those already expanded to be collapsed)
            if (expandedRows.data.length > 4 && expandedRows.data.filter(d => d.dataIndex === dataIndex).length === 0) return false;
            return true;
          },
          rowsExpanded: [0, 1],
          renderExpandableRow: (rowData, rowMeta) => {
            const colSpan = rowData.length + 1;
            return (
              <TableRow>
                <TableCell colSpan={colSpan}>
                  Custom expandable row option. Data: {JSON.stringify(rowData)}
                </TableCell>
              </TableRow>
            );
          },
          onRowExpansionChange: (curExpanded, allExpanded, rowsExpanded) => console.log(curExpanded, allExpanded, rowsExpanded)
        };
    
    

    It's from the example here. Just make sure if your data structure can work with the example (maybe you would need to adopt it a little bit).