简体   繁体   English

当 state 在上下文中更新时,.map() 不是 function

[英].map() is not a function when state is updated in Context

When updating the state, I'm getting the following error message noteList.map is not a function更新 state 时,我收到以下错误消息noteList.map is not a function

I have the following setup我有以下设置

src/pages/index.js Where my DragDropContainer is being mounted src/pages/index.js我的 DragDropContainer 正在安装的位置

const Index = ({ data, location }) => {
  // instantiate a map of notes
  const noteMap = new Map()
  for (const brainNote of data.allBrainNote.nodes) {
    const key = "/" + brainNote.slug
    noteMap.set(key, brainNote)
  }
  return (
    <Provider noteMap={noteMap} openNotes={[data.brainNote]}>
      <DragDropContainer location={location}></DragDropContainer>
    </Provider>
  )
}

src/components/DragDropContainer.js

import React, { useContext } from "react"
import { DragDropContext } from "react-beautiful-dnd"
import ColumnDroppable from "../components/columnDroppable"
import { Consumer, Context } from "../utils/notesContext"

...

const DragDropContainer = ({ location }) => {
  const notesContext = useContext(Context)
  const { openNotes, setOpenNotes } = notesContext

  ...

  return (
    <div>
      <div>
        <div style={{ display: "flex" }}>
          <DragDropContext onDragEnd={onDragEnd}>
            <Consumer>
              {context => (
                <div>
                  {context.openNotes.map((noteList, ind) => (
                    <ColumnDroppable
                      key={ind}
                      index={ind}
                      noteList={noteList}
                      location={location}
                    />
                  ))}
                </div>
              )}
            </Consumer>
          </DragDropContext>
        </div>
      </div>
    </div>
  )
}

export default DragDropContainer

src/components/columnDroppable.js

const ColumnDroppable = ({ index, noteList, location }) => {
  return (
    <Droppable key={index} droppableId={`${index}`}>
      {provided => (
        <div ref={provided.innerRef} {...provided.draggableProps}>
          {noteList.map((note, noteIdx) => ( // when updated this line throws an error
            <NoteContainer
              key={note.title}
              title={note.title}
              note={note}
              noteId={note.title}
              location={location}
              slug={note.slug}
              noteIdx={noteIdx}
            ></NoteContainer>
            // <Note key={note.id} title={note.title} note={note} note noteIdx={noteIdx} />
          ))}
          {provided.placeholder}
        </div>
      )}
    </Droppable>
  )
}

ColumnDroppable.propTypes = {
  index: PropTypes.node.isRequired,
}

export default ColumnDroppable

src/utils/notesContext.js

export const Context = createContext({})

export const Provider = props => {
  const { noteMap: initNoteMap, openNotes: initNote, children } = props

  const [noteMap, setNoteMap] = useState(initNoteMap)
  const [openNotes, setOpenNotes] = useState([initNote]) // openNotes is a 2D array

  const setNoteAsOpen = slug => {
    // note map has the key set to the slug of a note
    const isNoteAlreadyOpen = openNotes.some(note => {
      return note.slug === slug.slice(1)
    })
    if (isNoteAlreadyOpen) return // note is already open

    const openingNote = noteMap.get(slug)
    setOpenNotes([...openNotes, openingNote])
  }

  const notesContext = {
    noteMap,
    setNoteMap,
    openNotes,
    setOpenNotes,
    setNoteAsOpen,
  }

  return <Context.Provider value={notesContext}>{children}</Context.Provider>
}

export const { Consumer } = Context

src/components/CustomLinkToDraggable.js This is where setNoteAsOpen() is being called from src/components/CustomLinkToDraggable.js这是调用 setNoteAsOpen() 的地方

...
export const LinkToDraggableNote = React.forwardRef(
  ({ to, onClick, onMouseLeave, onMouseEnter, ...restProps }, ref) => {
    const notesContext = useContext(Context)
    const { openNotes, setNoteAsOpen } = notesContext

    const onClickHandler = ev => {
      console.log("within onclick handler")
      ev.preventDefault()

      setNoteAsOpen(to)
    }
    ...
   return (
      <Link
        {...restProps}
        to={to}
        ref={ref}
        onClick={onClickHandler}
        onMouseEnter={onMouseEnterHandler}
        onMouseLeave={onMouseLeaveHandler}
      />
    )

After setNoteAsOpen() is called I noticed that noteList in ColumnDroppable is still of type array, but not 100% why it is throwing the error.调用setNoteAsOpen()后,我注意到noteList中的 noteList 仍然是数组类型,但不是 100% 抛出错误的原因。

I also noticed that within setNoteAsOpen() the openNotes state is still the same after setOpenNotes() is called.我还注意到,在setNoteAsOpen()中,调用 setOpenNotes setOpenNotes() ) 后openNotes state 仍然相同。 As if setOpenNotes() didn't update the state.好像setOpenNotes()没有更新 state。 I'm not sure if this is related or causing the issue but figured I would point it out as well.我不确定这是否相关或导致问题,但我想我也会指出这一点。

Thanks in advance!提前致谢!

As I know when react renders the component first time, the value of context may not be initialized, so map will not be a function, Try giving an empty array as the default value for context ,据我所知,当 react 第一次渲染组件时, context 的值可能没有被初始化,所以 map 不会是 function,尝试给一个空数组作为 context 的默认值,

{(context=[])=> (
        <div>
            {context.openNotes.map((noteList, ind) => (
              <ColumnDroppable
                   key={ind}
                   index={ind}
                   noteList={noteList}
                   location={location}
                 />
               )}

it should fix the problem它应该解决问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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