简体   繁体   中英

Error: Objects are not valid as a React child (found: object with keys {low, high})

I'm pretty new to coding and this is my first post on Stack Overflow. I'm trying to build a React app. Here is the repo: https://github.com/Amaro-Koberle/k-net/

Here is a hosted version of the project (very early stages): https://quizzical-edison-523c55.netlify.app/

There are two components that cause an issue: NodeDisplay.js and EditNode.js . Both of those components render a list of all incoming and outgoing links (the app is a graph visualisation, when you click a node, a side-bar is supposed to display the content of the node and a list of all links that connect to it). I know that the issue is with this list, because when I comment the corresponding part out, things start working again. Whenever React tries to render either of those lists, the app crashes and I get this error: Error: Objects are not valid as a React child (found: object with keys {low, high}). If you meant to render a collection of children, use an array instead. Error: Objects are not valid as a React child (found: object with keys {low, high}). If you meant to render a collection of children, use an array instead.

NodeDisplay.js (the part that causes that the problem is currently commented out, hence you can click on a node in the hosted app without it crashing)

import { MdEdit } from "react-icons/md";
import { uuid } from "uuidv4";

export default function NodeDisplay({ currNode, setEditing }) {
  if (currNode.id === "") {
    console.log("No node is currently selected");
    return null;
  }

  return (
    <div className="mt-4">
      <div className="flex items-center space-x-2 text-lg">
        <h3>{currNode.title}</h3>
        <button className="edit-button" onClick={() => setEditing(true)}>
          <MdEdit></MdEdit>
        </button>
      </div>
      <div className="mt-4">
        <p className="text-sm">{currNode.description}</p>
        <div>
          <div className="mt-4">
            <h5>Incoming Links</h5>
            {/* <ul>
              {currNode.inLinks.map((link) => (
                <li key={uuid}>{link}</li>
              ))}
            </ul>
          </div>
          <div className="mt-4">
            <h5>Outgoing Links</h5>
            <ul>
              {currNode.outLinks.map((link) => (
                <li key={uuid}>{link}</li>
              ))}
            </ul> */}
          </div>
        </div>
      </div>
    </div>
  );
}

EditNode.js (here, the list isn't commented out, so the app still does crash when you try to edit a node (by clicking the little pencil icon)

import React from "react";
import { useState } from "react";
import { MdClose } from "react-icons/md";
import { uuid } from "uuidv4";

export default function EditNode({
  currNode,
  setCurrNode,
  setEditing,
  updateGraph,
  createLink,
  removeLink,
}) {
  const [sourceInput, setSourceInput] = useState("");
  const [targetInput, setTargetInput] = useState("");

  return (
    <div className="mt-4">
      <div className="flex items-center space-x-2 text-lg">
        <>
          <h3>Edit Node</h3>
        </>
        <>
          <button onClick={() => setEditing(false)}>
            <MdClose></MdClose>
          </button>
        </>
      </div>
      <form className="mt-4">
        {/* title and description */}
        <>
          <label className="label" htmlFor="title">
            Title
          </label>
          <>
            <input
              className="w-full input"
              type="text"
              id="title"
              placeholder="Title"
              value={currNode.title}
              onInput={(e) =>
                setCurrNode({ ...currNode, title: e.target.value })
              }
            ></input>
          </>
          <>
            <label className="label" htmlFor="description">
              Description
            </label>
            <>
              <textarea
                className="w-full input"
                rows="5"
                id="description"
                placeholder="Description"
                value={currNode.description}
                onInput={(e) =>
                  setCurrNode({ ...currNode, description: e.target.value })
                }
              ></textarea>
            </>
          </>
        </>
        {/* links */}
        <>
          {/* incoming links */}
          <div className="mt-4">
            <h4>Incoming Links</h4>
            <>
              <label className="label" htmlFor="createInLink">
                Source
              </label>
              <div className="inline-flex space-x-1">
                <input
                  className="input"
                  type="text"
                  id="createInLink"
                  placeholder="Source node ID"
                  value={sourceInput}
                  onInput={(e) => setSourceInput(e.target.value)}
                ></input>
                <>
                  <button
                    className="btn"
                    type="button"
                    onClick={() => createLink(sourceInput, currNode.id)}
                  >
                    Connect
                  </button>
                </>
              </div>
            </>
            <ul>
              {currNode.inLinks.map((link) => {
                return (
                  <li key={uuid()}>
                    <span>{link}</span>
                    <button
                      className="btn"
                      type="button"
                      onClick={() => removeLink(link, currNode.id)}
                    >
                      Remove
                    </button>
                  </li>
                );
              })}
            </ul>
          </div>
          {/* outgoing links */}
          <div className="mt-4">
            <h4>Outgoing Links</h4>
            <>
              <label className="label" htmlFor="createOutLink">
                Target
              </label>
              <div className="inline-flex space-x-1">
                <>
                  <input
                    className="input"
                    type="text"
                    id="createOutLink"
                    placeholder="Target node ID"
                    value={targetInput}
                    onInput={(e) => setTargetInput(e.target.value)}
                  ></input>
                </>
                <>
                  <button
                    className="btn"
                    type="button"
                    onClick={() => createLink(currNode.id, targetInput)}
                  >
                    Connect
                  </button>
                </>
              </div>
            </>
            <ul>
              {currNode.outLinks.map((link) => {
                return (
                  <li key={uuid()}>
                    <span>{link}</span>
                    <button
                      className="btn"
                      type="button"
                      onClick={() => removeLink(currNode.id, link)}
                    >
                      Remove
                    </button>
                  </li>
                );
              })}
            </ul>
          </div>
          {/* <button className="btn" type="button" onClick={updateGraph}>
            Save
          </button> */}
        </>
      </form>
    </div>
  );
}

There are other Stack Overflow questions in regards to this error, but reading the answers didn't help because I still don't understand the issue and I don't understand what changes are needed to fix it. I hope I'm not being a nuisance by asking again, in regards to my specific case.

Any help would be greatly appreciated.

In my case, changing <span>{link}</span> to <span>{link.low}</span> got rid of the error because that points react directly to the child.

What was confusing was that link wasn't supposed to have any properties called low or high . The hose came from some issue with h the javascript-driver of neo4j, which doesn't handle integers well. In the back-end, had to change

const nodes = nodesResult.records.map((r) => {
    return {
      id: r.get("id").toNumber(),
      inLinks: r.get("inLinks"),
      outLinks: r.get("outLinks"),
      title: r.get("title"),
      description: r.get("description"),
    };
  });

to

const nodes = nodesResult.records.map((r) => {
    return {
      id: r.get("id").toNumber(),
      inLinks: r.get("inLinks").map((inLink) => inLink.toNumber()),
      outLinks: r.get("outLinks").map((outLink) => outLink.toNumber()),
      title: r.get("title"),
      description: r.get("description"),
    };
  });

Notice I added .map((inLink) => inLink.toNumber()) and .map((outLink) => outLink.toNumber()) .

That fixed the issue, the data arriving at the front-end is now what I expected it to be (namely and array for inLinks and an array for outside Links , instead of an object with h keys high: and low: .

I hope this helps if anyone else runs into this issue.

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