React.js - 重新渲染时输入失去焦点

IT技术 javascript reactjs
2021-02-26 03:13:29

我只是写文本输入,onChange如果我调用setState,React 会重新渲染我的 UI。问题是文本输入总是失去焦点,所以我需要为每个字母再次聚焦:D。

var EditorContainer = React.createClass({

    componentDidMount: function () {
        $(this.getDOMNode()).slimScroll({height: this.props.height, distance: '4px', size: '8px'});
    },

    componentDidUpdate: function () {
        console.log("zde");
        $(this.getDOMNode()).slimScroll({destroy: true}).slimScroll({height: 'auto', distance: '4px', size: '8px'});
    },

    changeSelectedComponentName: function (e) {
        //this.props.editor.selectedComponent.name = $(e.target).val();
        this.props.editor.forceUpdate();
    },

    render: function () {

        var style = {
            height: this.props.height + 'px'
        };
        return (
            <div className="container" style={style}>
                <div className="row">
                    <div className="col-xs-6">
                    {this.props.selected ? <h3>{this.props.selected.name}</h3> : ''}
                    {this.props.selected ? <input type="text" value={this.props.selected.name} onChange={this.changeSelectedComponentName} /> : ''}
                    </div>
                    <div className="col-xs-6">
                        <ComponentTree editor={this.props.editor} components={this.props.components}/>
                    </div>
                </div>
            </div>
        );
    }

});
6个回答

没有看到您的其余代码,这是一个猜测。创建 EditorContainer 时,请为组件指定唯一键:

<EditorContainer key="editor1"/>

当重新渲染发生时,如果看到相同的键,这将告诉 React 不要破坏并重新生成视图,而是重用。然后焦点项目应该保持焦点。

@Petr Gladkikh 你的解决方案是对答案的补充。你们两个做得很好。让我的一天。
2021-04-29 03:13:29
支持@PetrGladkikh 的评论。我需要所有封闭组件上的键。
2021-05-03 03:13:29
在输入中添加键没有帮助
2021-05-11 03:13:29
这解决了我渲染包含输入表单的子组件的问题。但在我的情况下,我需要相反的 - 表单没有在我想要的时候重新渲染。添加键属性有效。
2021-05-12 03:13:29
也许包含您输入的组件也重新渲染。检查封闭组件上的键。
2021-05-14 03:13:29

我一次又一次地回到这里,总是在最后找到我在别处的解决方案。所以,我会在这里记录它,因为我知道我会再次忘记这一点!

input在我的案例中失去焦点的原因是因为我正在重新渲染input状态更改。

越野车代码:

import React from 'react';
import styled from 'styled-components';

class SuperAwesomeComp extends React.Component {
  state = {
    email: ''
  };
  updateEmail = e => {
    e.preventDefault();
    this.setState({ email: e.target.value });
  };
  render() {
    const Container = styled.div``;
    const Input = styled.input``;
    return (
      <Container>
        <Input
          type="text"
          placeholder="Gimme your email!"
          onChange={this.updateEmail}
          value={this.state.email}
        />
      </Container>
    )
  }
}

所以,问题是我总是在一个地方开始对所有内容进行编码以快速测试,然后将其全部分解为单独的module。但是,这里这个策略适得其反,因为在输入更改时更新状态会触发渲染功能并且焦点丢失。

修复很简单,从头做module化,也就是“把Input组件移出render功能”

固定码

import React from 'react';
import styled from 'styled-components';

const Container = styled.div``;
const Input = styled.input``;

class SuperAwesomeComp extends React.Component {
  state = {
    email: ''
  };
  updateEmail = e => {
    e.preventDefault();
    this.setState({ email: e.target.value });
  };
  render() {
    return (
      <Container>
        <Input
          type="text"
          placeholder="Gimme your email!"
          onChange={this.updateEmail}
          value={this.state.email}
        />
      </Container>
    )
  }
}

参考 解决方案:https : //github.com/styled-components/styled-components/issues/540#issuecomment-283664947

我觉得这是我的问题,但我无法移动的组件之外render()class ... extends Component由于参考this例如onChange={this.handleInputChange}
2021-04-18 03:13:29
故事的士气,对于React类组件,不要在render函数内部定义组件,对于React函数式组件,不要在函数体中定义组件。
2021-04-28 03:13:29
谢谢!你救了我的屁股!!
2021-05-02 03:13:29
我在渲染函数中使用了 HOC,将 HOC 调用移动到组件定义中就可以了。不知何故类似于这个答案。
2021-05-13 03:13:29
@Wong Jia Hau:当你在函数体中为 React 功能组件定义组件时会发生什么?我也遇到了类似的问题,并通过应用您的建议得到了解决。
2021-05-13 03:13:29

如果这是react-router中的问题,请<Route/>使用renderprop 而不是component.

<Route path="/user" render={() => <UserPage/>} />


失去焦点是因为componentpropsReact.createElement每次都使用而不是重新渲染更改。

详情请见:https : //reacttraining.com/react-router/web/api/Route/component

这基本上是我的问题。具体来说,我将一个匿名函数传递给组件道具,触发 focus-loss: <Route component={() => <MyComponent/>} />,当我应该做的时候<Route component={MyComponent} />
2021-04-19 03:13:29
谢谢你,这让我开心!
2021-04-23 03:13:29
请参阅stackoverflow.com/a/47660885/11667949就我而言,这有帮助
2021-04-26 03:13:29
你救了我的一天——就这么简单!
2021-05-06 03:13:29

我用钩子也有同样的症状。然而我的问题是在父级内部定义一个组件。

错误的:

const Parent =() => {
    const Child = () => <p>Child!</p>
    return <Child />
}

对:

const Child = () => <p>Child!</p>
const Parent = () => <Child />

只是为了扩展@ilkerkaran 所说的,因为 React 会Parent在每次状态更新时运行您的组件函数(函数),因此Child每次渲染inside都会不同。因此,React 不能在每次渲染中重用您的子组件,并且每次更新都会产生新元素。
2021-04-19 03:13:29
请注意,您仍然可以通过常规函数调用使用这样的嵌套子项。例如,return <div>{Child()}</div>可以,虽然无可否认有点难看。我有时发现将 JSX 表达式的不可重用部分提取到本地闭包中以提高可读性很有帮助,而不必使它们成为完整的独立组件并传递大量道具。焦点行为有点棘手。
2021-05-03 03:13:29
每次父级重新渲染时,它都会挂载子级
2021-05-11 03:13:29
const child应该是const Child,在“错误”的例子中。
2021-05-16 03:13:29

我的回答与@z5h 所说的相似。

就我而言,我曾经为组件Math.random()生成一个唯一key的。

我认为key仅用于触发该特定组件的重新渲染,而不是重新渲染该数组中的所有组件(我在我的代码中返回一个组件数组)。我不知道它用于在重新渲染后恢复状态。

删除它为我完成了工作。

请参阅stackoverflow.com/a/47660885/11667949就我而言,这有帮助
2021-04-18 03:13:29
npmjs.com/package/shortid这样的module也是处理此类事情的好方法。
2021-05-12 03:13:29