facebook/react · error · Error

60

60

Error message

Can only set one of `children` or `props.dangerouslySetInnerHTML`.

What it means

A single host element cannot take both children and dangerouslySetInnerHTML — there would be two competing sources of inner content. In setProp's dangerouslySetInnerHTML case, if nextHtml != null and props.children != null, React throws. Note it fires even for empty-looking children like '' or [] because only null/undefined pass.

Source

Thrown at packages/react-dom-bindings/src/client/ReactDOMComponent.js:662

          // For use by the polyfill.
          listenToNonDelegatedEvent('scroll', domElement);
        }
      }
      return;
    }
    case 'dangerouslySetInnerHTML': {
      if (value != null) {
        if (typeof value !== 'object' || !('__html' in value)) {
          throw new Error(
            '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +
              'Please visit https://react.dev/link/dangerously-set-inner-html ' +
              'for more information.',
          );
        }
        const nextHtml: any = value.__html;
        if (nextHtml != null) {
          if (props.children != null) {
            throw new Error(
              'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',
            );
          }
          const lastHtml: any =
            prevValue != null ? (prevValue as any).__html : undefined;
          if (lastHtml !== nextHtml) {
            domElement.innerHTML = nextHtml;
          }
        }
      }
      break;
    }
    // Note: `option.selected` is not updated if `select.multiple` is
    // disabled with `removeAttribute`. We have special logic for handling this.
    case 'multiple': {
      (domElement as any).multiple =
        value && typeof value !== 'function' && typeof value !== 'symbol';
      break;

View on GitHub (pinned to eafeac097b)

Solutions

  1. Remove the children/text from the element and keep only dangerouslySetInnerHTML
  2. In wrapper components, deliberately pick one: render children OR the html prop, never pass both through a spread
  3. Guard in your wrapper: choose dangerouslySetInnerHTML only when html != null, otherwise render children
  4. Check for accidental whitespace text nodes between opening and closing tags

Example fix

// before
<div {...props} dangerouslySetInnerHTML={{__html: html}}>fallback</div>

// after
<div {...props} {...(html != null ? {dangerouslySetInnerHTML: {__html: html}} : {})} />
// or explicitly: html != null ? <div {...props} dangerouslySetInnerHTML={{__html: html}}/> : <div {...props}>{children}</div>
Defensive patterns

Strategy: validation

Validate before calling

function renderContent({html, children, ...rest}: Props) {
  if (html != null && children != null) {
    // choose one instead of throwing downstream
    return <div {...rest} dangerouslySetInnerHTML={{__html: html}} />;
  }
  return html != null
    ? <div {...rest} dangerouslySetInnerHTML={{__html: html}} />
    : <div {...rest}>{children}</div>;
}

Type guard

const hasBothContentSources = (p: {html?: unknown; children?: unknown}) =>
  p.html != null && p.children != null;

Prevention

When it happens

Trigger: <div dangerouslySetInnerHTML={{__html: x}}>fallback</div>; whitespace-only JSX text between tags; spreading a props object that contains children while also setting dangerouslySetInnerHTML; conditional children that evaluate to a non-null falsy string.

Common situations: Wrapping markdown/html injection in a component that forwards props.children by default (HOC/spread patterns); template components with both a default children slot and an html prop; refactors that leave stray text inside the tag.

Related errors


AI-assisted analysis of facebook/react@eafeac097b (2026-08-21). Data as JSON: /api/errors/2b71db5da5086a62. Report an issue: GitHub.