【问题标题】:I am getting this error in the console : Cannot read property 'some' of undefined我在控制台中收到此错误:无法读取未定义的属性“某些”
【发布时间】:2019-09-04 08:47:22
【问题描述】:

TypeError: Cannot read property '' of undefined 我不知道为什么我会收到这个错误,而我检查下面的代码一切似乎都很好:(试图了解 react 的工作方式:) 那么这样做的目的是什么,因为我在 contextprovider 上包装了所有属性,例如联系人加载和我需要的功能

import React, { useState, useContext } from 'react'
import ContactContext from '../context/contactContext'

export default function ContactForm() {
  const name = useFormInput('')
  const email = useFormInput('')

  const contactContext = useContext(ContactContext)
  const { addContact } = contactContext

  const onSubmit = () => {
    addContact(name.value, email.value)
    name.onReset()
    email.onReset()
  }
  return (
   SOME HTML CODE HERE
  )
}

//contactState.js
import React, { useReducer } from 'react'
import _ from 'lodash'
import ContactContext from './contactContext'
import ContactReducer from './contactReducer'

const ContactState = props => {
  const initialState = {
    contacts: [
      {
        id: '098',
        name: 'Diana Prince',
        email: 'diana@us.army.mil'
      }
    ],
    loading: false,
    error: null
  }

  const [state, dispatch] = useReducer(ContactReducer, initialState)
  const [contacts, loading] = state
  const addContact = (name, email) => {
    dispatch({
      type: 'ADD_CONTACT',
      payload: { id: _.uniqueId(10), name, email }
    })
  }
  const delContact = id => {
    dispatch({
      type: 'DEL_CONTACT',
      payload: id
    })
  }
  return (
    <ContactContext.Provider
      value={{
        contacts,
        loading,
        addContact,
        delContact
      }}
    >
      {props.children}
    </ContactContext.Provider>
  )
}
export default ContactState

//contactReducer.js
export default (state, action) => {
  switch (action.type) {
    case 'ADD_CONTACT':
      return {
        contacts: [...state, action.payload]
      }
    case 'DEL_CONTACT':
      return {
        contacts: state.contacts.filter(
          contact => contact.id !== action.payload
        )
      }
    case 'START':
      return {
        loading: true
      }
    case 'COMPLETE':
      return {
        loading: false
      }
    default:
      throw new Error()
  }
}

//contactContext.js
import { createContext } from 'react'
const contactContext = createContext()
export default contactContext

【问题讨论】:

  • 这里出现错误:TypeError: Cannot read property 'addContact' of undefined
  • 似乎 contactContext 未定义

标签: javascript reactjs react-hooks react-context


【解决方案1】:

在您的 reducer 中,添加联系人时,您传播了错误的状态键。这应该可以解决它:

case 'ADD_CONTACT':
  return {
    contacts: [...state.contacts, action.payload]
  }

【讨论】:

    【解决方案2】:

    我看不到您在应用中使用ContactState 的位置。如果您不使用它并使用它渲染您的 ContactForm 组件,那么您将无法达到任何上下文值。您应该将其呈现为:

    <ContactState>
      <ContactForm />
    </ContactState>
    

    在您的应用中的合适位置。另外,你不能像这样得到contacts 和loading:

    const [ contacts, loading ] = state;
    

    state 不是数组,这里是对象。你应该使用:

    const { contacts, loading } = state
    

    您可以在下面找到您的代码的简化版本。我删除/更改了一些部分以尽可能多地运行它。您应该按照@Asaf David 在他们的回答中提到的那样修复您的减速器,但这不是这里的主要问题。修复上下文问题后,您可以尝试修复减速器。

    关于您的问题,如果您试图通过查看此示例来了解 React 的工作原理,您很容易感到困惑。因为Context 是一个高级概念(至少对于初学者来说)。此外,代码使用useReducer 和Context,这使事情变得更加复杂。如果您的意图是了解 React 本身,请从 beginner guide 开始。

    通过使用Context,我们可以将数据自上而下传递到最深的组件。但是,为了使用该数据,这些组件应呈现为上下文提供者的子级。

    在您的代码中,您在 ContactState 中执行此操作,但您从不使用它。此外,在该组件中,您使用useReducer 定义一个状态,并通过value 将此状态提供给您的上下文。

    最后,在您的ContactForm 组件中,您正在使用useContext 挂钩来获取上下文数据。在您当前的代码中,由于您没有在提供程序中呈现此组件,contactContext 未定义并且您收到错误消息。你不能从 undefined 得到addContact。

    在我的示例中,我正在检索 contacts 以显示某些内容。同样,我已经从您的代码中更改/删除了一些部分。

    const { createContext, useContext, useReducer } = React;
    
    const ContactContext = createContext();
    
    function ContactForm() {
      // Changed those values
      const name = "";
      const email = "";
    
      const contactContext = useContext(ContactContext);
      // changed addContact -> contacts
      const { contacts } = contactContext;
    
      const onSubmit = () => {
        addContact(name.value, email.value);
        name.onReset();
        email.onReset();
      };
      // added some data to render
      return <div>{contacts[0].name}</div>;
    }
    
    function ContactReducer(state, action) {
      switch (action.type) {
        case "ADD_CONTACT":
          return {
            contacts: [...state, action.payload]
          };
        case "DEL_CONTACT":
          return {
            contacts: state.contacts.filter(
              contact => contact.id !== action.payload
            )
          };
        case "START":
          return {
            loading: true
          };
        case "COMPLETE":
          return {
            loading: false
          };
        default:
          throw new Error();
      }
    }
    
    const ContactState = props => {
      const initialState = {
        contacts: [
          {
            id: "098",
            name: "Diana Prince",
            email: "diana@us.army.mil"
          }
        ],
        loading: false,
        error: null
      };
    
      const [state, dispatch] = useReducer(ContactReducer, initialState);
      const { contacts, loading } = state;
      const addContact = (name, email) => {
        dispatch({
          type: "ADD_CONTACT",
          // removed lodash part, added a static id
          payload: { id: 1, name, email }
        });
      };
      const delContact = id => {
        dispatch({
          type: "DEL_CONTACT",
          payload: id
        });
      };
      return (
        <ContactContext.Provider
          value={{
            contacts,
            loading,
            addContact,
            delContact
          }}
        >
          {props.children}
        </ContactContext.Provider>
      );
    };
    
    // added the relevant render part
    ReactDOM.render(
      <ContactState>
        <ContactForm />
      </ContactState>,
      document.getElementById("root")
    );
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <div id="root" />

    【讨论】:

    • serkan bey haklısınız array değil obje olarak yazdım yanlış yapmışım orada fakat yine çalıştıramadım
    • 你现在如何渲染ContactForm? PS:我使用的是英语,所以每个人都可以从这次对话中受益:)
    猜你喜欢
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多