我正在尝试在导航栏中获取onclick处理程序,以将不同的组件滚动到视图中。 我找到了一种可行的方法,但是我从反应中得到了警告,并且代码看起来不是很干净。我希望有人知道如何以更正确的方式解决此问题,从而消除警告并保持代码干净。
我将在每个组件上创建一个scrollTo,因此在Header.js中将几乎进行类似的调用,只是使用不同的名称。
这是应用程序的结构:
App.js
const App = () => {
return (
<div>
<Header />
<Banner />
<About />
<Technology />
<Contact />
<Portfolio />
</div>
);
};
Technology.js
const Technology = () => {
return (
<section className="technology">
<div className="heading white">
<h2>Technologies</h2>
<p>Some techno</p>
</div>
</section>
)
}
Header.js(导航栏)
const Header = () => {
let technology;
useEffect(() => {
technology = document.querySelector(".technology");
}, []);
return (
<header>
<p className="logo">Portfolio</p>
<div className="toggle"></div>
<ul>
<li>
<p onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}>
Home
</p>
</li>
<li>
<p>About Me</p>
</li>
<li>
<p onClick={() => technology.scrollIntoView({ behavior: "smooth" })}>
Technologies
</p>
</li>
<li>
<p>Contact</p>
</li>
<li>
<p>Projects</p>
</li>
</ul>
</header>
);
};
这是警告:
从React Hook内部分配给'technology'变量 每次渲染后useEffect将丢失。保留价值 时间,将其存储在useRef Hook中,并将可变值保留在 “ .current”属性。否则,您可以直接移动此变量 内部useEffect
要解决此问题,我想我需要将其从App.js传递到Header.js,并将其从每个组件传递到App.js?不幸的是,我的谷歌搜索技能不足以解决这个问题。
我知道在react中有一个用于此的库,但是我现在希望以一种更“原生”的方式解决这个问题。
答案 0 :(得分:1)
您可以使用函数ref灵活地执行此操作,这将允许元素将自身注册到通用ref
对象上。引用绝对是必经之路。您希望避免在使用React时尽可能直接访问DOM。
const { useRef } = React;
function App() {
const pageRefs = useRef({});
return (
<div className="app">
<Header pageRefs={pageRefs} />
<About pageRefs={pageRefs} />
<Technology pageRefs={pageRefs} />
<Portfolio pageRefs={pageRefs} />
</div>
);
};
function Header({ pageRefs }) {
function scrollIntoView(type) {
pageRefs.current[type].scrollIntoView({ behavior: "smooth" });
};
return (
<header>
<button onClick={() => scrollIntoView('about')}>
About
</button>
<button onClick={() => scrollIntoView('techno')}>
Technology
</button>
<button onClick={() => scrollIntoView('portfolio')}>
Portfolio
</button>
</header>
);
};
function About({ pageRefs }) {
return (
<section
className="page about"
ref={el => pageRefs.current = { ...pageRefs.current, about: el }}>
About
</section>
);
};
function Technology({ pageRefs }) {
return (
<section
className="page techno"
ref={el => pageRefs.current = { ...pageRefs.current, techno: el }}>
Technology
</section>
);
};
function Portfolio({ pageRefs }) {
return (
<section
className="page portfolio"
ref={el => pageRefs.current = { ...pageRefs.current, portfolio: el }}>
Portfolio
</section>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
* {
padding: 0;
margin: 0;
}
.app {
width: 100%;
}
.page {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.about {
background-color: crimson;
}
.techno {
background-color: lemonchiffon;
}
.portfolio {
background-color: cornflowerblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
答案 1 :(得分:0)
您可以为此使用回调。
export const scrollIntoView = (selector, option) => (event) => {
const el = document.querySelector(selector);
if (!el) return;
el.scrollIntoView(option);
};
用法。
import { scrollIntoView } from 'path/to/file';
const scrollIntoViewTechnology = scrollIntoView('.technology', { behavior: "smooth" });
const Component = () => {
return (
<button type='button' onClick={scrollIntoViewTechnology}>Lorem Ipsum</button>
);
};