警告:在 StrictMode 中不推荐使用 findDOMNode。findDOMNode 传递了一个在 StrictMode 内的 Transition 实例

Nir*_*ish 88 javascript strict-mode reactjs react-component react-state

我正在尝试使用一个函数作为组件内的道具,而这个组件是另一个组件的子组件。但该功能不起作用。?我能知道为什么吗。这是我在控制台中收到的警告。

警告:在 StrictMode 中不推荐使用 findDOMNode。findDOMNode 传递了一个位于 StrictMode 内的 Transition 实例。相反,直接向要引用的元素添加 ref

这是我的代码

class Todo extends Component {
  state = {
    show: false,
    editTodo: {
      id: "",
      title: "",
      isCompleted: false
    }
  }
  handleClose = () => {
    this.setState({ show: false })
  }
  handleShow = () => {
    this.setState({ show: true })
  }
  getStyle () {
    return {
      background: '#f4f4f4',
      padding: '10px',
      borderBottom: '1px #ccc dotted',
      textDecoration: this.props.todo.isCompleted ? 'line-through'
        : 'none'
    }
  }
  //this method checks for changes in the edit field
  handleChange = (event) => {
    this.setState({ title: event.target.value })
    console.log(this.state.editTodo.title);
  }

  render () {
    //destructuring
    const { id, title } = this.props.todo;
    return (
      <div style={this.getStyle()}>
        <p>
          <input type='checkbox' style={{ margin: "0px 20px" }} onChange={this.props.markComplete.bind(this, id)} /> {''}
          {title}
          <Button style={{ float: "right", margin: "0px 10px" }} variant="warning" size={"sm"} onClick={this.handleShow}>Edit</Button>{' '}
          <Button style={{ float: "right" }} variant="danger" size={"sm"} onClick={this.props.DelItem.bind(this, id)}>Delete</Button>
        </p>
        <Modal show={this.state.show} onHide={this.handleClose}>
          <Modal.Header closeButton>
            <Modal.Title>Edit your Task!</Modal.Title>
          </Modal.Header>
          <Modal.Body >
            <FormGroup >
              <Form.Control
                type="text"
                value={this.state.editTodo.title}
                onChange={this.handleChange}
              />
            </FormGroup>
          </Modal.Body>
          <Modal.Footer>
            <Button variant="secondary" onClick={this.handleClose}>
              Close
                          </Button>
            <Button variant="primary" onClick={this.handleClose}>
              Save Changes
                          </Button>
          </Modal.Footer>
        </Modal>
      </div>
    )

  }
}
Run Code Online (Sandbox Code Playgroud)

use*_*035 62

在 index.js 中更改<React.StrictMode><App /><React.StrictMode><App />,您将不会看到此警告。请注意,严格模式可以帮助您

  • 识别生命周期不安全的组件
  • 关于旧字符串引用 API 使用的警告
  • 有关已弃用的 findDOMNode 用法的警告
  • 检测意外的副作用
  • 检测遗留上下文 API

删除之前请参考https://reactjs.org/docs/strict-mode.html

  • 如何解决这个根本原因? (52认同)
  • 更好地解决根本原因 (21认同)
  • 它不能解决任何问题,只是隐藏警告 (6认同)
  • 当警告来自第三方库时,这是有用的解决方案。 (5认同)

Fra*_*mes 30

如果您从react-bootstrap解决方法中使用 Modal 或 Carousel禁用动画。关闭它们会使警告消失。

对于模态:

<Modal animation={false}>
    <Modal.Header closeButton>
        <Modal.Title>Title</Modal.Title>
    </Modal.Header>
    <Modal.Body>
        Content
    </Modal.Body>
</Modal>
Run Code Online (Sandbox Code Playgroud)

对于轮播:

<Carousel slide={false} fade={false}>
    <Carousel.Item>
      Scene 1
    </Carousel.Item>
    <Carousel.Item>
      Scene 2
    </Carousel.Item>
</Carousel>
Run Code Online (Sandbox Code Playgroud)

我知道一旦它不回答 OP 问题,它更适合作为评论,但我没有足够的声誉来这样做,也许它可以帮助某人。

  • 如果你使用 React Bootstrap 中的 OverlayTrigger,设置 `transition={false}` 就可以了。 (3认同)
  • 请注意:当您运行构建版本时,警告似乎消失了。 (2认同)

Bin*_*Man 27

@Ross Allen 的响应与基本问题(警告)无关,它解决了代码中的语法问题。

@Ali Rehman 的回应更多地与警告有关,但它也没有正确解决问题,它只是隐藏了问题,使警告不再出现.. 如果我们不关心弃用,为什么不呢!

是的,问题来自 React.StrictMode:

<React.StrictMode>
 <App />
</React.StrictMode>
Run Code Online (Sandbox Code Playgroud)

StrictMode 是一种用于突出应用程序中潜在问题的工具。它会为其后代激活额外的检查和警告,例如:

  • 识别生命周期不安全的组件
  • 关于旧字符串引用 API 使用的警告
  • 有关已弃用的 findDOMNode 用法的警告
  • 检测意外的副作用
  • 检测遗留上下文 API

由于问题中没有完全给出错误回溯,我猜这个问题与关于已弃用的 findDOMNode 用法警告有关,因为在渲染方法中引用了元素:

<Modal show={this.state.show} onHide={this.handleClose}>
      <Modal.Header closeButton>
        <Modal.Title>Edit your Task!</Modal.Title>
      </Modal.Header>
      <Modal.Body >
        <FormGroup >
          <Form.Control
            type="text"
            value={this.state.editTodo.title}
            onChange={this.handleChange}
          />
        </FormGroup>
      </Modal.Body>
      <Modal.Footer>
        <Button variant="secondary" onClick={this.handleClose}>
          Close
                      </Button>
        <Button variant="primary" onClick={this.handleClose}>
          Save Changes
                      </Button>
      </Modal.Footer>
    </Modal>
Run Code Online (Sandbox Code Playgroud)

当组件被渲染时,模态也被渲染了,我们尝试改变组件的状态,组件(以及模态)将重新渲染,在这个阶段模态无法访问状态.

解决警告的解决方案是使用React refs。Refs 有助于访问在 render 方法中创建的 DOM 节点或 React 元素。

  • 您能提供一些例子吗?你说的对我来说很有道理。我尝试将 `ref={myRef}` 设置为模态并将 `target={myRef}` 设置为按钮,但我仍然收到警告。我正在使用带有钩子的函数组件。谢谢! (6认同)
  • 兄弟你得到答案了吗 (2认同)

Ros*_*len 23

setState电话看起来像它被写入到错误的地方。确保它在editTodo对象上:

    handleChange = (event) => {
        this.setState(state => ({
          editTodo: {
            ...state.editTodo,
            title: event.target.value,
          },
        }));
    }
Run Code Online (Sandbox Code Playgroud)

  • 您不必担心该警告。我猜它来自您用于“Modal”和“Button”组件的任何库(也许是react-bootstrap?)。它警告该功能已被弃用,但这意味着它仍然可以正常工作,但将在 React 的未来版本中删除。 (24认同)
  • @RossAllen 来自 `react-transition-group` 的 `css-transtion` 创建了相同的警告 (9认同)
  • 答案确实与标题中提出的问题无关,您的评论更适合作为答案,而答案更适合作为评论恕我直言。 (3认同)

Ali*_*son 13

React Semantic UI中,这是一个已知问题,他们的大多数组件仍在使用findDOMNode()。这已在Semantic UI React v3 PR #4233中得到修复,所有这些组件都将更新为使用React.forwardRef().

起初我以为我做错了什么,并花了很长时间进行调查,结果发现这是一个已知问题。

PR #4233的一个有趣的边缘情况可能会有所帮助,那就是除了组件之外的所有组件都可以转换为功能组件<Dropdown>。为此,他们使用函数组件包装组件forwardRef,然后将innerRefprop 传递给类组件(通过PR commit diff):

const Dropdown = React.forwardRef((props, ref) => {
  return <DropdownInner {...props} innerRef={ref} />
})

class DropdownInner extends Component {
  searchRef = createRef()
  sizerRef = createRef()
  ref = createRef()
  ...
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢伙计...我已经花了很多时间来找到你的评论:) (2认同)

Era*_* Or 7

我不确定它在使用 material-ui 库时是否有帮助,但在许多情况下这会有所帮助:

const nodeRef = React.useRef(null);
return <div>
  <CSSTransition ... nodeRef={nodeRef}>
    <div ref={nodeRef}> ... </div>
  </CSSTransition>
</div>
Run Code Online (Sandbox Code Playgroud)

  • 太好了,这实际上消除了警告。如果您可以添加解释为什么这可能有效,将会很有帮助!此外,如果由于样式问题而无法添加包装器,则可能无法包装附加的 div 并附加引用。`React.forwardRef` 在这种情况下会有所帮助,如[这个答案](/sf/answers/4424354721/)中所述 (2认同)
  • 首先感谢您的见解。1.在文档中,它说当传递nodeRef prop时,不会传递node,这使您能够在CSSTransition内传递ref元素。2. 组件包装div不是必需的。它可以是一个片段。 (2认同)
  • 使用“react-transition-group”时的正确答案 (2认同)

小智 6

这是MaterialUI库的问题,在新的MaterialUI v5正式发布之前,这里有一个临时解决方案