You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用getElementById修改元素innerHTML时触发TypeError: Cannot set property 'innerHTML' of null错误的排查与方案咨询

Let's break down what's going wrong here and fix it the React way—since you're using React, direct DOM manipulation like getElementById and innerHTML is almost never the right approach, and that's exactly why you're hitting this error.

Why You're Getting TypeError: Cannot set property 'innerHTML' of null

Let's unpack the root causes:

  1. Your onClick is firing immediately, not on user click
    Writing onClick={togglePopup(player.username)} runs the function as soon as the component renders, not when the button is clicked. This triggers state updates prematurely, and when you try to call document.getElementById(name) right after, the DOM element might not exist yet (or the state hasn't updated to reflect the change), so it returns null.

  2. You can't inject JSX via innerHTML
    JSX compiles to React element objects, not raw HTML strings. Shoving JSX into innerHTML won't render it correctly—it'll just treat it as plain text (or throw errors) because React isn't handling the rendering.

  3. React state updates are asynchronous
    When you call setIsOpen(!isOpen), the state doesn't update instantly. Trying to manipulate the DOM right after this call means you're working with the old state, which doesn't match the current DOM state.

The Correct React Approach: Use State to Control Rendering

Instead of fighting React by manipulating the DOM directly, leverage React's declarative model—describe what UI should show based on state, and let React handle the rest. Here's how to fix your code:

Step 1: Update State to Track Active Popup

Instead of a boolean isOpen, use a state variable to track which player's popup is open (since you have multiple players):

import { useState } from 'react';

// Track the username of the player whose popup is active (null = no popup open)
const [activePopupUsername, setActivePopupUsername] = useState(null);

const togglePopup = (username) => {
  // Toggle: if the popup is already open for this user, close it; else open it
  setActivePopupUsername(prev => prev === username ? null : username);
};

// Update handleKick to close the popup after action
const handleKick = (playerId) => {
  // Add your kick logic here (API call, state update, etc.)
  console.log(`Kicking player with ID: ${playerId}`);
  
  // Close the popup once action is done
  setActivePopupUsername(null);
};

Step 2: Rewrite the Render Logic

Remove all DOM manipulation code, and render the popup conditionally based on the activePopupUsername state:

return (
  <>
    <legend className="text-xl mb-5 border-yellow-500 border-l-4 pl-2 mt-10">Team Members</legend>
    <div className="flex gap-5 flex-col w-full mb-4">
      {props.team.players.map((player, key) => (
        <div key={key} className="">
          <label htmlFor="csgoign" className="flex bg-gray-50 hover:bg-gray-200 p-3 rounded-xl w-full items-center justify-between">
            <div className="flex font-medium gap-3">
              <img 
                src={`https://robohash.org/${player.username}?set=set5`} 
                className="w-12 h-12 rounded-3xl bg-blue-100"
                alt={`Avatar for ${player.username}`}
              />
              <div className="ml-3">
                <a 
                  href={`http://localhost:3000/userprofile/${player._id}`} 
                  className="text-2xl w-auto font-semibold hover:text-yellow-600"
                >
                  {player.username}
                </a>
                <p className="text-sm font-normal text-gray-700 font-paragraph">
                  Member since : {player.join_date}
                </p>
              </div>
            </div>
            {/* Only show kick button/popup if current user is team cap and not viewing their own profile */}
            {props.user._id === props.team.team_cap && player.username !== props.user.username && (
              <div>
                {activePopupUsername !== player.username ? (
                  // Show Kick button when no popup is active for this player
                  <button 
                    type="button" 
                    onClick={() => togglePopup(player.username)} 
                    className="border font-semibold text-xl border-red-300 rounded-xl hover:bg-red-600 px-7 py-2"
                  >
                    Kick
                  </button>
                ) : (
                  // Show popup when this player's popup is active
                  <div className="popup-box">
                    <div className="flex flex-col box gap-1">
                      <div>
                        <p className="font-medium text-lg">Are you sure you want to kick {player.username} ?</p>
                      </div>
                      <div className="flex flex-row gap-14 items-center justify-center">
                        <button 
                          type="button" 
                          onClick={() => handleKick(player._id)} 
                          className="border font-semibold text-lg border-red-300 rounded-xl hover:bg-red-600 px-6"
                        >
                          Yes
                        </button>
                        <button 
                          onClick={() => togglePopup(player.username)} 
                          className="border font-semibold text-lg border-yellow-300 rounded-xl hover:bg-yellow-500 px-6"
                        >
                          No
                        </button>
                      </div>
                    </div>
                  </div>
                )}
              </div>
            )}
          </label>
        </div>
      ))}
    </div>
  </>
);

Key Improvements

  • No more DOM manipulation: All UI changes are controlled by React state, so your UI and state will always stay in sync.
  • Per-player popup control: The state tracks exactly which player's popup is open, so clicking "Kick" on one player won't affect others.
  • Correct onClick handling: Using arrow functions (onClick={() => togglePopup(player.username)}) ensures the function only runs when the button is clicked.
  • Cleaner logic: The popup is rendered directly in the component tree, making it easier to maintain and debug.

内容的提问来源于stack exchange,提问作者Prasesh Maharjan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:42:54