Maison  >  Questions et réponses  >  le corps du texte

React rapporte les accessoires. "fonction" n'est pas une fonction

<p>Je crée ma première boutique en ligne et je rencontre un problème. J'ai créé une fausse API qui contient des données de fiche produit et lorsque je les reçois en utilisant <code>axios.get</code> et que j'ajoute à l'état, j'obtiens "props.addCardData n'est pas une fonction".Je dois dire que tout fonctionne bien jusqu'à ce que j'ajoute <code>axios.get</code> Autres fonctions que j'utilise de la même manière que la fonction <code>addCardData</code> : je veux dire, j'ai utilisé <code>mapDispatchToProps</code> je ne les utilise pas dans <code>axios.get</code> ou dans d'autres requêtes). Je n’ai eu aucun problème à utiliser aucune des fonctionnalités auparavant. </p> <p>Je prévois d'obtenir les données via <code>axios.get</code> et d'appeler une fonction à partir du conteneur de cartes qui appellera la répartition avec le créateur d'action comme paramètre. </p> <p>J'ai également trouvé "Impossible de lire la propriété non définie (lire 'addCardData').</p> <p>Ci-dessous, j'ai indiqué la partie du code affectée par le problème (j'ai indiqué quel code s'applique à quels éléments)</p> <p>Voici le code du composant Cartes (je n'ai pas ajouté les importations ici, mais bien sûr j'ai toutes les importations) : </p> <pre class="brush:php;toolbar:false;">const Cartes = (accessoires) => axios.get('https://mocki.io/v1/8cb0f160-92f7-4cf8-a6c1-f63690df514e') .then(réponse => { props.addCardData(response.data) }) laissez cardsArray = Object.keys(props.cardsData).map(card => ( <OffreCarte clé={carte.id} bg={props.cardsData[card].bg} id={props.cardsData[card].tagId} title={props.cardsData[card].title} text={props.cardsData[card].text} bouton={ <Liquide du conteneur> <Row className={'row-cols-auto'}> {props.cardsData[card].button.map(bouton => ( <Bouton Cartes clé={bouton.id} lien={bouton.link} type={bouton.type} classe={bouton.class} nom={bouton.nom} /> ))} </Ligne> </Conteneur> } /> )) retour ( <Liquide du conteneur> <img src={'./backgrounds/bestoffers.png'} alt={'MEILLEURES OFFRES'} className={'img-fluid imgTab'} /> <Row xs={1} md={2} id={'cards-row'} className={'border border-4 g-3'}> {/*row-cols-* – définit la largeur des cartes en définissant le nombre de cartes dans la ligne*/} {cartesArray} </Ligne> </Conteneur> ) } exporter les cartes par défaut</pre> <p>Voici le code dans <code>CardsContainer</code> : </p> <pre class="lang-js Prettyprint-override"><code>const mapStateToProps = (state) => retour { CardsData : state.homePage.cardsData } } const mapDispatchToProps = (envoi) => retour { addCardData : (données) => expédition (addCardsData (données)) } } } const CardsContainer = connect(mapStateToProps, mapDispatchToProps)(Cartes); exporter le conteneur de cartes par défaut </code></pre> <p>Voici le code dans le réducteur : </p> <pre class="lang-js Prettyprint-override"><code>... homePageCardsData = 'HOMEPAGE-CARDS-DATA' initialState = {...} - inclut "cardsData : {}" const homePageReducer = (état = état initial, action) => laissez stateCopy ; commutateur (action.type) { cas homePageCardsData : { stateCopy = {...état, cardsData : action.data} casser } ... par défaut : état de retour ; } retourner l'étatCopie ; ...... - quelques fonctions ici (pas besoin de savoir) }exporter const addCardsData = (données) => tapez : accueilPageCardsData, données : données }) </code></pre> <p>Quand j'essaie quelque chose comme : </p> <pre class="lang-js Prettyprint-override"><code>const addCard = props.addCardData axios.get('https://mocki.io/v1/8cb0f160-92f7-4cf8-a6c1-f63690df514e') .then(réponse => { addCard (réponse.données) }) </code></pre> <p>J'ai du retard sur localhost (sur la page d'accueil !!), tout commence à s'afficher lentement, et 70 % du temps, le blocage de la carte ne s'effectue pas. Dans d'autres cas, le rendu peut s'effectuer après un certain temps (rare chance). Sur la page AdminPanel, j'affiche <code>Cards</code> car j'ai besoin de voir les modifications lors du test du menu, j'obtiens "TypeError : addCard n'est pas une fonction". <p>Si je supprime ce code du composant, tout fonctionne correctement. </p> <p>Je dois aussi dire que j'ai utilisé le "débogueur" et que je l'ai placé dans <code>homePageCardsData</code>. Le script s'arrête sur le débogueur (après <code>StateCopy</code> et avant <code>break</code>). Cela signifie que le script est correct, <code>dispatch</code> fonctionne et que je peux entrer dans le cas <code>homePageCardsData</code>. </p>
P粉475315142P粉475315142433 Il y a quelques jours635

répondre à tous(1)je répondrai

  • P粉807471604

    P粉8074716042023-09-05 09:01:34

    Le problème est Cards 组件中,它直接在组件的函数体中将 Axios GET 请求作为无意的副作用。这很可能会创建一个渲染循环,或者至少在每次 Cards de faire une requête GET lors du rendu.

    Déplacez ce code dans un hook useEffect afin qu'il soit appelé une fois le composant installé.

    Exemple :

    const Cards = ({ addCardsData, cardsData }) => {
      useEffect(() => {
        axios
          .get("https://mocki.io/v1/8cb0f160-92f7-4cf8-a6c1-f63690df514e")
          .then((response) => {
            addCardsData(response.data);
          });
      }, [addCardsData]);
    
      let cardsArray = Object.keys(cardsData).map((card) => (
        <OfferCard
          key={card.id}
          bg={cardsData[card].bg}
          id={cardsData[card].tagId}
          title={cardsData[card].title}
          text={cardsData[card].text}
          button={
            <Container fluid>
              <Row className={"row-cols-auto"}>
                {cardsData[card].button.map((button) => (
                  <CardsButton
                    key={button.id}
                    link={button.link}
                    type={button.type}
                    class={button.class}
                    name={button.name}
                  />
                ))}
              </Row>
            </Container>
          }
        />
      ));
    
      return (
        ...
      );
    };
    
    const mapStateToProps = (state) => ({
      cardsData: state.homePage.cardsData
    });
    
    const mapDispatchToProps = {
      addCardsData
    };
    
    const CardsContainer = connect(mapStateToProps, mapDispatchToProps)(Cards);

    Vous utilisez du code Redux assez ancien que nous n'utilisons généralement plus connect 高阶组件,因为 useDispatchuseSelector 挂钩取代了它的用法。目前的标准是使用 Redux-Toolkit, ce qui réduit la quantité de passe-partout que vous devez écrire.

    Voici des exemples de suggestions de mise à jour :

    import { useDispatch, useSelector } from "react-redux";
    ...
    
    const Cards = () => {
      const dispatch = useDispatch();
      const cardsData = useSelector(state => state.homePage.cardsData);
    
      useEffect(() => {
        axios
          .get("https://mocki.io/v1/8cb0f160-92f7-4cf8-a6c1-f63690df514e")
          .then((response) => {
            dispatch(addCardsData(response.data));
          });
      }, [dispatch]);
    
      let cardsArray = Object.keys(cardsData).map((card) => (
        <OfferCard
          key={card.id}
          bg={cardsData[card].bg}
          id={cardsData[card].tagId}
          title={cardsData[card].title}
          text={cardsData[card].text}
          button={
            <Container fluid>
              <Row className={"row-cols-auto"}>
                {cardsData[card].button.map((button) => (
                  <CardsButton
                    key={button.id}
                    link={button.link}
                    type={button.type}
                    class={button.class}
                    name={button.name}
                  />
                ))}
              </Row>
            </Container>
          }
        />
      ));
    
      return (
        ...
      );
    };

    code du réducteur, type d'opération, créateur d'opération... le tout remplacé par une seule tranche d'état.

    import { createSlice } from "@reduxjs/toolkit";
    
    const initialState = {
      cardsData: {},
      ... other home page state ...
    };
    
    const homePageSlice = createSlice({
      name: "homePage",
      initialState,
      reducers: {
        addCardsData: (state, action) => {
          state.cardsData = action.payload;
        },
        ... other reducer cases ...
      }
    });
    
    export const {
      addCardsData,
      ... other generated actions ...
    } = homePageSlice.actions;
    
    export default homePageSlice.reducer;
    

    répondre
    0
  • Annulerrépondre