Javascript addEventListener在React中为空
我正在使用React创建搜索功能。我以前使用过这种方法,但没有使用React,而且效果很好。现在,它在控制台中出现了一个错误,称为“UncaughtTypeError:无法读取null的属性'addEventListener'。这和它在英国制造有什么关系吗?我该如何解决这个问题Javascript addEventListener在React中为空,javascript,reactjs,Javascript,Reactjs,我正在使用React创建搜索功能。我以前使用过这种方法,但没有使用React,而且效果很好。现在,它在控制台中出现了一个错误,称为“UncaughtTypeError:无法读取null的属性'addEventListener'。这和它在英国制造有什么关系吗?我该如何解决这个问题 <body> <div id="searching"></div> <script type="text/babel"> class SearchBox exten
<body>
<div id="searching"></div>
<script type="text/babel">
class SearchBox extends React.Component { render(){ return(
<form>
<input type="text" className="searchbox" />
</form>) } } ReactDOM.render(
<SearchBox />, document.getElementById("searching"));
</script>
类SearchBox扩展React.Component{render(){return(
)}}ReactDOM.render(
,document.getElementById(“搜索”);
JS
const端点=”https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';
常量存储库=[];
获取(端点)
.then(blob=>blob.json())
.then(data=>repositories.push(…data));
函数FindMatch(wordToMatch,存储库){
返回存储库。过滤器(位置=>{
const regex=new RegExp(wordToMatch,“gi”);
return place.city.match(regex)| | place.state.match(regex);
});
};
函数displayMatches(){
const matchArray=findMatches(this.value,repositories);
常量html=matchArray.map(位置=>{
const regex=new RegExp(this.value,“gi”);
const cityName=place.city.replace(regex,`${this.value}`);
const stateName=place.state.replace(regex,`${this.value}`);
返回`
${cityName},${stateName}
${numberWithCommas(place.population)}
`;
}).加入(“”);
log(匹配数组);
suggestions.innerHTML=html;
};
const searchInput=document.querySelector(“.searchbox”);
const suggestions=document.querySelector(“.suggestions”);
searchInput.addEventListener(“更改”,显示匹配项);
searchInput.addEventListener(“键控”,显示匹配项);
一般来说,将ReactJS与非ReactJS混合使用是个坏主意。React有一种非常特殊的处理事件的方法,直接调用addEventListener()
时效果不佳。调用addEventListener()
时,有时很可能会正常工作,但您确实不应该依赖于此
不应将两者混合使用的原因是React可以在任何时候自由地重建DOM:任何时候出现状态更改,React都可以自行拆除DOM元素并创建新的元素,而不是您的元素。你既不知道也不关心元素何时被渲染,这就是React的一部分美
那么,你如何处理事件呢?在创建元素时,您必须使用诸如onChange
和onKeyUp
之类的属性,以一种老派的方式将它们连接起来。(在引擎盖下,React实际上会在正确的时间使用addEventListener
,但您从未真正注意到这种情况发生。)
那么,您的代码的修订版本的结构可能如下所示:
class SearchBox extends React.Component {
constructor(props) {
super(props);
// This binding is necessary to make `this` work in the callback
this.onKeyUp = this.onKeyUp.bind(this);
this.onChange = this.onChange.bind(this);
}
onChange(event) {
...
}
onKeyUp(event) {
...
}
render() {
return(
<form>
<input type="text" className="searchbox" onChange={this.onChange} onKeyUp={this.onKeyUp} />
</form>
);
}
}
ReactDOM.render(
<SearchBox />,
document.getElementById("searching")
);
类搜索框扩展了React.Component{
建造师(道具){
超级(道具);
//此绑定是使`This`在回调中工作所必需的
this.onKeyUp=this.onKeyUp.bind(this);
this.onChange=this.onChange.bind(this);
}
onChange(事件){
...
}
onKeyUp(事件){
...
}
render(){
返回(
);
}
}
ReactDOM.render(
,
document.getElementById(“搜索”)
);
正如您所看到的,代码的整个结构是不同的。React不仅仅是一种轻松发布HTML元素的方式:它是一个完整的基于组件的微框架,您可以围绕它设计整个UI。我不同意肖恩的观点。使用本机函数很好,事实上,有时您必须这样做 出现此错误的原因是脚本试图将侦听器添加到不存在的DOM节点:当侦听器脚本执行时,输入元素尚未刷新到DOM。这就是为什么当您需要以这种方式获取转义图案填充时,您应该在componentdidmount中从组件本身内部执行此操作,并且仅当子节点需要侦听完全未连接的父DOM节点时(例如,该节点可能位于组件所属的其他React子树之外)。这保证您试图查找的节点已经存在
这就是说,通过这种方式使用本机函数,在95%的常见用例中应该也可以避免一个逃生舱。您应该使用更惯用的方法,将状态提升到更高级别的组件,或者如果确实需要,使用ref。取决于上述答案和其他地方的参考。我尝试了下面的方法,并进行了锻炼
class Searchbox extends React.Component {
state = {};
componentDidMount = () => { //Used for when component mounts for first time
myfunction();
}
componentDidUpdate = () => { //Used for every time component updates
myfunction();
}
myfunction = () => {
// This is function which contains addEventListeners
// or statements like - document.getElementId("myDiv");
}
render() {
return (
<div id="myDiv">
...
// body of code to render
</div>
);
}
}
export default Searchbox;
类搜索框扩展了React.Component{
状态={};
componentDidMount=()=>{//用于组件首次装载时
myfunction();
}
componentDidUpdate=()=>{//用于每次组件更新
myfunction();
}
myfunction=()=>{
//这是包含addEventListeners的函数
//或者像-document.getElementId(“myDiv”)这样的语句;
}
render(){
返回(
...
//要渲染的代码体
);
}
}
导出默认搜索框;
我同意@Sean的观点。本机java和ReactJS有不同的生命周期来处理事件。
我添加了一些使用钩子的人。您可以使用useffect和useRef添加自定义钩子
如果使用React,则不应使用addEventListener。在这里读一下。此外,在这种情况下,您应该使用
onInput
^他所说的内容。这些元素似乎在JS运行时不存在,可能是因为它们还没有被渲染,所以我会使用它们?我不确定
class Searchbox extends React.Component {
state = {};
componentDidMount = () => { //Used for when component mounts for first time
myfunction();
}
componentDidUpdate = () => { //Used for every time component updates
myfunction();
}
myfunction = () => {
// This is function which contains addEventListeners
// or statements like - document.getElementId("myDiv");
}
render() {
return (
<div id="myDiv">
...
// body of code to render
</div>
);
}
}
export default Searchbox;
function useEventListener(eventName, handler, element = window){
// Create a ref that stores handler
const savedHandler = useRef();
// Update ref.current value if handler changes.
// This allows our effect below to always get latest handler ...
// ... without us needing to pass it in effect deps array ...
// ... and potentially cause effect to re-run every render.
useEffect(() => {
savedHandler.current = handler;
}, [handler]);
useEffect(
() => {
// Make sure element supports addEventListener
// On
const isSupported = element && element.addEventListener;
if (!isSupported) return;
// Create event listener that calls handler function stored in ref
const eventListener = event => savedHandler.current(event);
// Add event listener
element.addEventListener(eventName, eventListener);
// Remove event listener on cleanup
return () => {
element.removeEventListener(eventName, eventListener);
};
},
[eventName, element] // Re-run if eventName or element changes
);
};
export default useEventListener;