0

Hi I build a single page app to search by name,while I input any character in search bar there appear to be type error,so I use FLOW to check and down below are two errors.I was toldincompatible-use,but what is right use,anyone could give me some document to read?

Error -------------------------------------------------------------------------------------- src/component/List.js:22:25
Cannot get `data.students` because property `students` is missing in undefined [1]. [incompatible-use]

   src/component/List.js:22:25
   22|     const newarr = data.students.map(student => {
                               ^^^^^^^^

References:
   src/component/List.js:10:27
   10|   const [data, setData] = useState();
                                 ^^^^^^^^^^ [1]


Error -------------------------------------------------------------------------------------- src/component/List.js:68:31
Cannot build a typed interface for this module. You should annotate the exports of this module with types. Missing type
annotation at function return: [signature-verification-failure] 

Below is my code:

// @flow
import React, { useState, useEffect } from "react";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";
import Avatar from "@material-ui/core/Avatar";
import TextField from "@material-ui/core/TextField";

function User({ login }) {
  const [data, setData] = useState();

  useEffect(() => {
    if (!login) return;
    fetch(`https://api.hatchways.io/assessment/${login}`)
      .then((response) => response.json())
      .then(setData)
      .catch(console.error);
  }, [login]);

  const handleNameSearch = (e) => {
    const newarr = data.students.map((student) => {
      if (
        student.firstName.toUpperCase().includes(e.target.value.toUpperCase())
      )
        return student;
      else if (
        student.lastName.toUpperCase().includes(e.target.value.toUpperCase())
      )
        return student;
      else return null;
    });
    const result = newarr.filter((student) => student !== undefined);
    setData({ students: result });
  };

  if (data)
    return [
      <Paper
        style={{
          maxWidth: 600,
          maxHeight: 300,
          marginLeft: 300,
          marginRight: 300,
          marginBottom: 10,
        }}
      >
        <TextField
          onChange={handleNameSearch}
          id="standard-basic"
          label="Search by name"
          style={{ width: 600 }}
        />
      </Paper>,
      <div>
        {data.students.map((student, index) => {
          const newgrades = student.grades.map((x) => +x);
          return (
            <Paper
              key={student.id}
              style={{
                maxWidth: 600,
                maxHeight: 300,
                marginLeft: 300,
                marginRight: 300,
              }}
            >
              <Grid container spacing={1}>
                <Grid item style={{ marginTop: 50, marginRight: 0 }}>
                  <Avatar style={{ width: 100, height: 100 }}>
                    <img
                      src={student.pic}
                      alt="avatar"
                      style={{ width: 100, height: 100 }}
                    />
                  </Avatar>
                </Grid>
                <Grid item style={{ marginLeft: 30 }}>
                  <h1>{student.firstName + " " + student.lastName}</h1>
                  <section>
                    <p>Email:{student.email}</p>
                    <p>Company:{student.company}</p>
                    <p>Skill:{student.skill}</p>
                    <p>
                      Average:
                      {newgrades.reduce(
                        (accumulator, currentValue) =>
                          accumulator + currentValue,
                      ) / newgrades.length}
                      %
                    </p>
                  </section>
                </Grid>
              </Grid>
            </Paper>
          );
        })}
      </div>,
    ];

  return null;
}

export default function List() {
  return <User login="students" />;
}

I also create in the link to help my helpers to test or play:https://codesandbox.io/s/ecstatic-cache-2swtl

Brianzchen
  • 1,265
  • 5
  • 21
juexu
  • 131
  • 2
  • 11

2 Answers2

0

Your issue is because when data is initialised in the useState() call, it is undefined, if you were to run handleNameSearch immediately you'll find that it would crash because data is undefined, as your flow error says, so then data.students would crash, and flow is throwing an error to prevent this.

There are a number of ways to prevent this, either you return null early above the creation of your handleNameSearch function though this is probably wrong given what you're trying to accomplish as a filter.

I doubt the rest of your logic would function properly if we simply ignore this error though so to get you by, I would suggest you just do the simplest thing and only run the code block if data is populated

  const handleNameSearch = (e) => {
    if (!data) return;

    const newarr = data.students.map((student) => {
      if (
        student.firstName.toUpperCase().includes(e.target.value.toUpperCase())
      )
        return student;
      else if (
        student.lastName.toUpperCase().includes(e.target.value.toUpperCase())
      )
        return student;
      else return null;
    });
    const result = newarr.filter((student) => student !== undefined);
    setData({ students: result });
  };
Brianzchen
  • 1,265
  • 5
  • 21
  • I tried your solution but it did not work,I also doubt usestate does not update state sync so I replace `setData({ students: result });`with `setData(() => { return { students: result } });` within`handleNameSearch`.my solution was inspired by `https://reactjs.org/docs/faq-state.html#what-does-setstate-do ` and `https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately`.I will search more material to share with you,thanks – juexu Feb 28 '21 at 02:28
0

I replacesetData({ students: result });with setData(() => { return { students: result } }) and replace const result = newarr.filter((student) => student !== undefined); with const result = newarr.filter((student) => student !== null);within handleNameSearch .the live search Works well

juexu
  • 131
  • 2
  • 11