我正在使用React创建一个搜索功能。我以前用过这种方法,但没有反应,而且起了作用。现在,它在控制台中出现了一个错误:"Uncaught :无法读取属性'addEventListener‘of null“。这和它的反应有关吗?我该怎么解决这个问题?
<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>
JS
const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';
const repositories = [];
fetch(endpoint)
.then(blob => blob.json())
.then(data => repositories.push(...data));
function findMatches(wordToMatch, repositories) {
return repositories.filter(place => {
const regex = new RegExp(wordToMatch, "gi");
return place.city.match(regex) || place.state.match(regex);
});
};
function displayMatches() {
const matchArray = findMatches(this.value, repositories);
const html = matchArray.map(place => {
const regex = new RegExp(this.value, "gi");
const cityName = place.city.replace(regex, `<span class="hl">${this.value}</span>`);
const stateName = place.state.replace(regex, `<span class="hl">${this.value}</span>`);
return `
<li>
<span class="name">${cityName}, ${stateName}</span>
<span class="population">${numberWithCommas(place.population)}</span>
</li>
`;
}).join('');
console.log(matchArray);
suggestions.innerHTML = html;
};
const searchInput = document.querySelector(".searchbox");
const suggestions = document.querySelector(".suggestions");
searchInput.addEventListener("change", displayMatches);
searchInput.addEventListener("keyup", displayMatches);发布于 2017-03-01 12:56:18
通常情况下,将ReactJS与非ReactJS的做事方式相结合是个坏主意。React有一种非常特殊的处理事件的方法,直接调用addEventListener()也不太好。当您调用addEventListener()时,它有时会工作的可能性很小,但是您真的不应该依赖它。
您不应该将两者混合在一起的原因是,React可以在任何时候任意重建DOM :任何时候发生状态更改时,React都可以删除DOM元素并创建新的元素,而不是您的元素。你既不知道也不关心元素何时呈现,这是反应美的一部分。
那么你是如何处理这些事件的呢?在创建元素时,您必须使用像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不仅仅是一种轻松地发出HTML元素的方法:它是一个基于组件的微框架,您可以围绕这个框架来设计整个UI。
发布于 2017-03-01 13:07:32
我不同意肖恩的看法。使用本机函数是可以的,实际上有时您必须这样做。
出现此错误的原因是脚本试图将侦听器添加到不存在的DOM节点:当侦听器脚本执行时,您的输入元素尚未被刷新到DOM。这就是为什么当您需要以这种方式访问一个转义口时,您应该在组件内部,在compnentDidMount中这样做,并且只有当一个子节点需要在一个完全不连接的父DOM节点上侦听时才这样做--例如,这个节点可能在其他反应性子树yiur组件所属的外部。这保证了您试图查找的节点已经存在。
尽管如此,以这种方式使用本机函数是一个逃避舱口,在95%的常见用例中应该也可以避免。您应该使用更多的惯用方式,要么将状态提升到更高级别的组件,要么在真正需要时使用ref。
发布于 2020-05-14 18:42:49
我同意肖恩的观点。本机java和ReactJS有不同的生命周期来处理事件。我在增加一些使用钩子的人。您可以使用useEffect和useRef添加自定义钩子。
下面是创建useEventListener自定义钩子的示例代码。我从https://usehooks.com/useEventListener/得到了这个示例代码
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;https://stackoverflow.com/questions/42532087
复制相似问题