首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >反应-可加载的重呈现导致输入失去焦点。

反应-可加载的重呈现导致输入失去焦点。
EN

Stack Overflow用户
提问于 2018-07-03 22:51:48
回答 1查看 1.1K关注 0票数 1

我遇到了一个问题,react-loadable导致我的一个输入组件在状态更新后重新呈现并失去焦点。我已经做了一些调查,我找不到有这个问题的其他人,所以我想我在这里遗漏了一些东西。

我试图根据用户选择的主题使用react-loadable动态地将组件包含到我的应用程序中。这很好用。

/组件/应用程序

代码语言:javascript
复制
import React from 'react';
import Loadable from 'react-loadable';

/**
 * Import Containers
 */
import AdminBar from '../../containers/AdminBar';
import AdminPanel from '../../components/AdminPanel';

import 'bootstrap/dist/css/bootstrap.css';
import './styles.css';

const App = ({ isAdmin, inEditMode, theme }) => {
    const MainContent = Loadable({
        loader: () => import('../../themes/' + theme.name + '/components/MainContent'),
        loading: () => (<div>Loading...</div>)
    });

    const Header = Loadable({
        loader: () => import('../../themes/' + theme.name + '/components/Header'),
        loading: () => (<div>Loading...</div>)
    });

    return (
        <div>
            {
                (isAdmin) ? <AdminBar
                                className='admin-bar'
                                inEditMode={inEditMode} /> : ''
            }
            <Header
                themeSettings={theme.settings.Header} />
            <div className='container-fluid'>
                <div className='row'>
                    {
                        (isAdmin && inEditMode) ? <AdminPanel
                                                    className='admin-panel'
                                                    theme={theme} /> : ''
                    }
                    <MainContent
                        inEditMode={inEditMode} />
                </div>
            </div>
        </div>
    );
};

export default App;

./构成部分/管理小组

代码语言:javascript
复制
import React from 'react';
import Loadable from 'react-loadable';

import './styles.css';

const AdminPanel = ({ theme }) => {
    const ThemedSideBar = Loadable({
        loader: () => import('../../themes/' + theme.name +  '/components/SideBar'),
        loading: () => null
    });

    return (
        <div className='col-sm-3 col-md-2 sidebar'>
            <ThemedSideBar
                settings={theme.settings} />
        </div>
    );
};

export default AdminPanel;

这就是我的<ThemedSideBar />组件的样子:

/主题/默认/组件/侧栏

代码语言:javascript
复制
import React from 'react';

import ThemeSettingPanel from '../../../../components/ThemeSettingPanel';
import ThemeSetting from '../../../../containers/ThemeSetting';

import './styles.css';

const SideBar = ({ settings }) => {
    return (
        <ThemeSettingPanel
            name='Header'>
            <ThemeSetting
                name='Background Color'
                setting={settings.Header}
                type='text'
                parent='Header' />
            <ThemeSetting
                name='Height'
                setting={settings.Header}
                type='text'
                parent='Header' />
        </ThemeSettingPanel>
    );
};

export default SideBar;

/组件/主题设置小组

代码语言:javascript
复制
import React from 'react';
import { PanelGroup, Panel } from 'react-bootstrap';

const ThemeSettingPanel = ({ name, children }) => {
    return (
        <PanelGroup accordion id='sidebar-accordion-panelGroup'>
            <Panel>
                <Panel.Heading>
                    <Panel.Title toggle>{name}</Panel.Title>
                </Panel.Heading>
                <Panel.Body collapsible>
                    {children}
                </Panel.Body>
            </Panel>
        </PanelGroup>
    );
};

export default ThemeSettingPanel;

./容器/主题设置

代码语言:javascript
复制
import React, { Component } from 'react';
import { connect } from 'react-redux';

import { themeSettingChange } from '../App/actions';

import ThemeSetting from '../../components/ThemeSetting';

class ThemeSettingContainer extends Component {
    constructor(props) {
        super(props);

        this.handleOnChange = this.handleOnChange.bind(this);
    }

    handleOnChange(name, parent, value) {
        const payload = {
            name: name,
            parent,
            value: value
        };

        this.props.themeSettingChange(payload);
    }

    render() {
        return (
            <ThemeSetting
                name={this.props.name}
                setting={this.props.setting}
                parent={this.props.parent}
                type={this.props.type}
                handleOnChange={this.handleOnChange} />
        );
    }
}

//----Redux Mappings----//
const mapStateToProps = (state) => ({
});

const mapDispatchToProps = {
    themeSettingChange: (value) => themeSettingChange(value)
};

export default connect(mapStateToProps, mapDispatchToProps)(ThemeSettingContainer);

/组件/主题设置

代码语言:javascript
复制
import React from 'react';

import TextField from '../common/TextField';

import './styles.css';

const ThemeSetting = ({ name, setting, type, parent, handleOnChange }) => {
    return (
        <div className='row theme-setting'>
            <div className='col-xs-7'>
                {name}
            </div>
            <div className='col-xs-5'>
                {
                    generateField(type, setting, name, parent, handleOnChange)
                }
            </div>
        </div>
    );
};

function generateField(type, setting, name, parent, handleOnChange) {
    const value = setting ? setting[name] : '';

    switch (type) {
        case 'text':
            return <TextField
                        value={value}
                        name={name}
                        parent={parent}
                        handleOnChange={handleOnChange} />;
        default:
            break;
    }
}

export default ThemeSetting;

/组件/公共/TextField

代码语言:javascript
复制
import React from 'react';
import { FormControl } from 'react-bootstrap';

const TextField = ({ value, name, parent, handleOnChange }) => {
    return (
        <FormControl
            type='text'
            value={value}
            onChange={(e) => {
                handleOnChange(name, parent, e.target.value);
            }} />
    );
};

export default TextField;

当更新“我的管理面板”中的字段时,会触发状态更改。这似乎触发了react-loadable重新呈现我的<ThemedSideBar />组件,这破坏了我的输入,并创建了一个具有更新值的新输入。还有其他人有这个问题吗?有办法阻止react-loadable重新呈现吗?

编辑:这里是到回购请求的链接。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-04 01:09:19

编辑:根据评论中的对话,很抱歉,我误解了这个问题。这里的答案是更新的(原来的答案在更新的答案下面)

更新答复

react可加载文档的角度来看,可加载的自组织似乎是要在render方法之外调用的。在您的示例中,您将ThemedSideBar加载到AdminPanel的呈现方法中。我怀疑您的TextEdit输入的更改,传递到更新您的Redux状态,然后通过组件链返回,导致考虑重新呈现AdminPanel。因为您对Loadable的调用在render方法中(即AdminPanel是表示组件),react-loadable每次响应到该代码路径时都会呈现一个全新的加载组件。因此,React认为需要销毁之前的组件,以便适当地更新组件与新的props。

这样做是可行的:

代码语言:javascript
复制
import React from 'react';
import Loadable from 'react-loadable';

import './styles.css';

const ThemedSideBar = Loadable({
  loader: () => import('../../themes/Default/components/SideBar'),
  loading: () => null
});

const AdminPanel = ({ theme }) => {
    return (
        <div className='col-sm-3 col-md-2 sidebar'>
            <ThemedSideBar
                settings={theme.settings} />
        </div>
    );
};

export default AdminPanel;

原始答案

看起来,您的问题可能与您构建TextField而不是react-loadable的方式有关。

FormControlvalue={value}onChange处理程序作为道具。这意味着您已经表明它是一个受控组件(相对于不受控制)。

如果希望字段在用户输入时接受更新的值,则需要传播onChange处理程序捕获的更改,并确保将其反馈给value={value}支柱中的值。

现在,看起来value总是等于theme.settings.Height等(大概为空/空)。

另一种选择是使FormControl成为一个不受控制的组件,但我猜您不想这样做。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51163746

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档