简体   繁体   中英

react typescript : usestate type

I'm trying to get my project from firebase and put it in an array with hooks.

One project look like: {name: "movie app", date: t, description: "this is my first app, a complete movie app"}

//hooks
const [projects, setProject] = useState([]);

//function for get projects
async function getprojects(){
    let finalProjects = [];
    await db.collection('projects').get().then((querySnapshot) => {
        querySnapshot.docs.map(res => {
             const a = res.data();
             finalProjects.push(a)
        })
        //error here
        setProjects(finalProjects)
    })
}

useEffect(() => {
    getprojects();
}, []);

But finalProjects.push(res.data()) doesn't work because "Argument of type 'DocumentData' is not assignable to parameter of type 'never'." But how I'm suppose to put all my project into projects with setProjects

Typescript doesn't know what you are storing in the state, so it won't let you put data into it. You can either make it an any array (less ideal) or a DocumentData array.

const [projects, setProject] = useState<any[]>([]);
const [projects, setProject] = useState<DocumentData[]>([]);

Make sure DocumentData is in scope, imported from firestore .

or you could do something like this. This way you will get your state typed and you will also get the doc.data() typed (I think, somebody that is better at this can maybe verify this)

import {
  collection,
  getFirestore,
  getDocs,
  query,
  orderBy,
  DocumentData,
} from "firebase/firestore";

export interface ArticleProps {
  authorId: string;
  authorName: string;
  category: CategoryProps[];
  content: [];
  created: number;
  eventDate: number;
  heroImage: string;
  htmlData: string;
  preview: string;
  published: boolean;
  title: string;
  type: string;
  users: UserIdProps[];
}


const [allArticles, setAllArticles] = useState<ArticleProps[]>([]);
  const fetchEvents = async () => {
    const eventsRef = await collection(db, "events");
    const q = query(eventsRef, orderBy("created"));
    const snapShot = await getDocs(q);
    const eventsList: ArticleProps[] = [];
    snapShot.forEach((doc: DocumentData) => {
      return eventsList.push(doc.data());
    });
  };

My suggestion:

  1. Rename useState hook so the only difference between the two are "set" and a capital letter.

  2. Refactor the function to an arrow function and optimize it with a useCallback hook and try/catch.

  3. Assuming it is an array you want, setting it to the res.data instead of mapping it.

  4. Setting an if statement inside useEffect to not accidentally call it more than you have to.

  5. Using it in your return by mapping it there projects.map(project =>...)

Suggestion in code format:

 // Hooks const [projects, setProjects] = useState<Array | undefined>(); // Arrow function for get projects const getProjects = useCallback(async () => { try { const res = await db.collection('projects').get(); return setProjects(res.data); } catch { // Error here setProject([]); } }, []); useEffect(() => { if(;projects) { getProjects(), } }; [projects]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM