作为一个 React Native 新手,我正在开发一个适用于 android 的应用程序。基本上,该应用程序使用户能够根据特定的搜索参数过滤数据库。
现在我尝试将类组件转换为功能组件。该组件只加载一个预填充的 (Realm-( 数据库,显示一个等待用户输入的搜索栏,根据用户的输入执行数据库查询并显示结果。
在"旧"版本中,数据库设置是在componentDidMount()
期间完成的,现在我认为使用useEffect()
Hook 可以完成这项工作,因为它可以替代componentDidMount()
。但我发现在没有任何 Hook 的情况下"裸露"地完成所有逻辑(我实际上想放入 Hook(就可以了。
由于这种行为,我感到非常困惑,因为我没想到它会以这种方式工作。我当然错过了什么。不幸的是,谷歌搜索没有给出答案。你可以帮我吗?下面是我正在谈论的组件的代码,SearchBar.js
非常感谢您的帮助!
import React, {useState} from 'react';
import {View, Text, StyleSheet} from 'react-native';
import {connect} from 'react-redux';
import {Header, Icon, Item, Input} from 'native-base';
import Realm from 'realm';
import fs from 'react-native-fs';
import {setInputValueSearchBar} from '../../../actions';
const SearchBar = props => {
let [inputValue, setInputValue] = useState(null);
const sendInputValueToReduxStore = text => {
setInputValue(text);
props.setInputValueSearchBar(text);
};
// from here on, I wanted to use useEffect() ...
const dogsSchema = {
name: 'realm',
properties: {
name: 'string?',
color: 'string?',
},
};
let realm = new Realm({
path: fs.DocumentDirectoryPath + '/default.realm',
schema: [dogsSchema],
readOnly: true,
});
const dogs = realm.objects('realm');
let resultArray = [];
const databaseRequest = () => {
const query = inputValue;
const result = inputValue
? dogs.filtered("name == '" + query + "'")
: 'default';
resultArray = Array.from(result);
return resultArray.map(dog => (
<Text className="dog" key={dog.name}>
{dog.name}
</Text>
));
};
//... until here
const isText = props.text;
return (
<View>
<Header searchBar rounded>
<Item>
<Icon name="ios-search" />
<Input
placeholder="Search"
onChangeText={text => sendInputValueToReduxStore(text)}
value={inputValue}
/>
</Item>
</Header>
<View>{databaseRequest()}</View>
</View>
);
};
function mapStateToProps(state) {
return {
inputValue: state.inputValue,
};
}
const mapDispatchToProps = {
setInputValueSearchBar,
};
export default connect(mapStateToProps, mapDispatchToProps)(SearchBar);
这是重构之前与类组件相同的组件:
import React from 'react';
import {View, Text, StyleSheet} from 'react-native';
import {connect} from 'react-redux';
import {Header, Icon, Item, Input} from 'native-base';
import Realm from 'realm';
import fs from 'react-native-fs';
import {setInputValueSearchBar} from '../../../actions';
class SearchBar extends React.Component {
state = {
inputValue: null,
};
sendInputValueToReduxStore(text) {
this.setState({inputValue: text});
this.props.setInputValueSearchBar(text);
}
componentWillMount() {
const dogsSchema = {
name: 'realm',
properties: {
name: 'string?',
color: 'string?',
},
};
let realm = new Realm({
path: fs.DocumentDirectoryPath + '/default.realm',
schema: [dogsSchema],
readOnly: true,
});
const dogs = realm.objects('realm');
let resultArray = [];
this.databaseRequest = () => {
const query = this.state.inputValue;
const result = this.state.inputValue
? dogs.filtered("name == '" + query + "'")
: 'default';
resultArray = Array.from(result);
return resultArray.map(dog => (
<Text className="dog" key={dog.name}>
{dog.name}
</Text>
));
};
}
render() {
const isText = this.props.text;
return (
<View>
<Header searchBar rounded>
<Item>
<Icon name="ios-search" />
<Input
placeholder="Search"
onChangeText={text => this.sendInputValueToReduxStore(text)}
value={this.state.inputValue}
/>
</Item>
</Header>
{isText && (
<View>
<Text>{this.props.text}</Text>
</View>
)}
<View>{this.databaseRequest()}</View>
</View>
);
}
}
function mapStateToProps(state) {
return {
inputValue: state.inputValue,
};
}
const mapDispatchToProps = {
setInputValueSearchBar,
};
export default withNavigation(
connect(mapStateToProps, mapDispatchToProps)(SearchBar),
);
当然,它可以在没有useEffect
的情况下工作。 但每次重新渲染组件时也会发生这种情况。 这可能不是应用程序中的问题,原因如下:
- 也许您的组件不会经常重新渲染,具体取决于您正在管理/更新的状态以及位置
- 也许逻辑是一个微不足道的资源消耗,是否经常执行并不重要
但是,如果情况并非如此,您可能需要衡量并确认正在发生的事情。 在此处向设置逻辑添加一些日志记录输出,并在日志中观察调用频率。
如果它没有经常被重新调用(或者至少不是不合理地经常(,那么你当然可以保持这样。 请注意,它可能会开始根据此组件之外的因素不断重新调用,任何会导致此组件重新渲染的因素。
如果它不断被重新调用,那么这就是useEffect
的目的。 您只能在第一次加载组件时执行此逻辑,因为没有依赖项:
useEffect(() => {
// your logic
}, []);
或者,您可以添加依赖项以在依赖项更改时触发执行此逻辑。 例如,可以在inputValue
更改时随时重新调用它:
useEffect(() => {
// your logic
}, [inputValue]);
性能方面,这不是一个好方法。
代码在每次渲染时执行,因此每次 prop 或状态值更改时,即使它与该代码段无关。
useEffect
钩子也执行每个渲染,BUT 允许您传递依赖项列表(如果没有依赖项,则传递空列表,则执行一次(。然后,代码将仅在其中一个依赖项更改时执行。