我是React的初学者,仍在学习过程中,请多多包涵。我的React应用出现问题,因为输入一个字母后输入内容失去了焦点。我已经将文本字段单独分解为一个组件。但是,当我在其他组件中的元素上调用setState
时,似乎会导致该问题。
在一个大组成部分DropdownTextComponent
下,我有三个组成部分DisplayedColumnsList
,AvailableColumnsList
和DropdownComponent
。
这是我的DropdownComponent
,其中包含三个不同的组件。
const DropdownComponent = (props) => {
return (
<div className = "dropdown-column">
<Dropdown
isOpen = {this.state.dropdownOpen}
onClose = {() => this.setOpen(false)}
>
{props.dropdownsearch}
{props.displayedcolumns}
{props.availablecolumns}
</Dropdown>
</div>
);
}
这是我的DropdownTextComponent
:
const DropdownTextComponent = () => {
return (
<div className = "dropdown-text-input">
<TextInput
onChange = {this.dropdownSearch}
value = {this.state.dropdownValue}
>
</TextInput>
</div>
)
}
这是方法dropdownSearch
,称为onChange
:
dropdownSearch(e) {
this.state.dropdownValue = e.target.value;
let resultCols = this.state.columns;
let dropdownSearchList = []
let dropdownSet = new Set();
for (let i = 0; i < resultCols.length; i++) {
if (resultCols[i].text.includes(e.target.value)) {
dropdownSet.add(resultCols[i]);
}
}
dropdownSearchList = [...dropdownSet]
this.setState({
toggleColumnList : dropdownSearchList
})
}
现在toggleColumnList
用于两个不同的组件DisplayedColumnsList
和AvailableColumnsList
中,因此我假设在此处使用setState
时,不应重新渲染DropdownTextComponent
。但是这样做,我的输入字段失去了焦点。我已将setState部分注释掉,并且工作正常。
我想知道问题出在哪里以及如何解决。如果您需要更多信息,请告诉我。
答案 0 :(得分:0)
像这样的东西可以更好地工作?
class App extends React.Component {
constructor (props) {
super(props)
this.state = {
toggleColumnList: []
dropdownValue: '',
columns: [ { text: 'some text'}, { text: 'some other text'} ]
}
}
dropdownSearch = (e) => {
const value = e.target.value;
let resultCols = this.state.columns;
let dropdownSearchList = []
let dropdownSet = new Set();
for (let i = 0; i < resultCols.length; i++) {
if (resultCols[i].text.includes(e.target.value)) {
dropdownSet.add(resultCols[i]);
}
}
dropdownSearchList = [...dropdownSet]
this.setState({
dropdownValue: value,
toggleColumnList : dropdownSearchList
})
}
render () {
const { columns, toggleColumnList, dropdownValue } = this.state
return (
<DropdownComponent>
<DropdownTextComponent value={dropdownValue} onChange={this.dropdownSearch}/>
<DisplayedColumnsList columns={toggleColumnList.length ? toggleColumnList : columns} />
<AvailableColumnsList columns={toggleColumnList.length ? toggleColumnList : columns} />
</DropdownComponent>
)
}
}
class DropdownComponent extends React.Component {
constructor (props) {
super(props)
this.state = {
isOpen: true
}
}
close = () => {
this.setState({
isOpen: false
})
}
render () {
return (
<div className = "dropdown-column">
<Dropdown
isOpen={this.state.isOpen}
onClose={this.close}
>
{ props.children }
</Dropdown>
</div>
)
}
}
const DropdownTextComponent = (props) => {
const { onChange, value } = props
return (
<div className = "dropdown-text-input">
<TextInput
onChange={onChange}
value={value}
/>
</div>
)
}
更新
通常,我试图想象您的组件结构如何。
主要要点是希望您的DropdownTextComponent仅在其值或其更改事件处理程序更改时才呈现。
对于这种情况,您应该避免每次渲染DropdownComponent时都像以前那样显式渲染它,但是让React为您处理重新渲染。
当您执行类似props={ <DropdownTextComponent /> }
的操作时,括号内的表达式会在组件的每次渲染时立即求值。此外,您没有将任何内容传递给子组件。
但是,如果您这样做<DropdownComponent><DropdownTextComponent value={value} onChange={onChange} /></DropdownComponent>
,React将解析您App的整个结构,并仅在其属性或状态改变时才渲染每个节点。
为此,由于父级是自定义组件,因此您必须在其render方法中显式添加其子级。您可以使用特殊的React道具children
来完成此任务,该道具包含您已定义为组件后代的所有内容。