调用时 useState 不更新
useState doesn't update when called
我正在构建一个餐厅网站模板。在项目中,我确实有一个带有两个箭头按钮的模式框来更改页面。我通过 useState 跟踪 pageNumber
变量。不幸的是,该值永远不会更新,这会阻止页面更改。
这是 Menu.js 组件:
import { BrowserRouter as Router, Link } from 'react-router-dom';
import { useState } from 'react';
const Menu = () => {
let [pageNumber, switchPage] = useState(1);
let dish = {
categories: [
'proin blandit',
'suspendisse non',
'fermentum ultrices',
'volutpat vulputat'
],
names: [
['Sed fermentum', 'Sapien nec lobortis', 'Tristique in suspendisse', 'Pellentesque mattis elit', 'Vel interdum velit'],
['Nam nisi quam', 'Donec non viverra', 'Morbi suscipit mattis', 'Sed dignissim nisi', 'Aliquam vitae'],
['Curabitur ante mi', 'Nulla a felis', 'Donec porta convallis ', 'Vestibulum viverra ', 'Nullam viverra '],
['Vestibulum odio', 'Mauris neque ligula', 'Praesent iaculis nunc', 'Cras sollicitudin est', 'Class aptent taciti ']
],
prices: [
[13.99, 11.99, 15.99, 17.99, 21.99],
[22.99, 20.99, 18.99, 16.99, 24.99],
[11.99, 21.99, 31.99, 25.99, 15.99],
[6.99, 8.99, 10.99, 4.99, 8.99]
]
}
let iterator = Math.abs(pageNumber % 4);
let lineBreak = window.innerWidth <= 750 ? <br/> : undefined;
return (
<Router>
<section className='menu'>
<i className='fas fa-chevron-circle-left' id='menu-arrow-left' onClick={() => switchPage(pageNumber - 1)}></i>
<h1 className='dish-category'>You are viewing {dish.categories[iterator]}</h1>
<Link to='/home'><i className='fas fa-times'></i></Link>
<ul className='dish-list'>
<li className='dish'>{dish.names[iterator][0]} {lineBreak} <span className='price'>{dish.prices[iterator][0]} PLN</span></li>
<li className='dish'>{dish.names[iterator][1]} {lineBreak} <span className='price'>{dish.prices[iterator][1]} PLN</span></li>
<li className='dish'>{dish.names[iterator][2]} {lineBreak} <span className='price'>{dish.prices[iterator][2]} PLN</span></li>
<li className='dish'>{dish.names[iterator][3]} {lineBreak} <span className='price'>{dish.prices[iterator][3]} PLN</span></li>
<li className='dish'>{dish.names[iterator][4]} {lineBreak} <span className='price'>{dish.prices[iterator][4]} PLN</span></li>
</ul>
<i className='fas fa-chevron-circle-right' id='menu-arrow-right' onClick={() => switchPage(pageNumber + 1)}></i>
</section>
</Router>
)
}
export default Menu;
这是我切换模式可见性的方式:
const hideModal = (e) => {
e.preventDefault();
let placeholder = document.getElementById('placeholder');
placeholder.innerText = '';
placeholder.style.display = 'none';
let container = document.getElementById('container');
container.style.filter = '';
container.style.pointerEvents = 'auto';
}
const showModal = () => {
let placeholder = document.getElementById('placeholder');
placeholder.innerHTML = ReactDOMServer.renderToString(<Menu />);
placeholder.style.display = 'block';
let container = document.getElementById('container');
container.style.filter = 'blur(8px)';
container.style.pointerEvents = 'none';
}
这是App.js中对应的JSX代码:
<div id='placeholder'><Menu /> <Contact /></div>
另外,我写了一个检测点击位置的测试函数。当我在上面的示例中 运行 它时,我收到一条消息,指出我在模式框外单击,即使它是相反的。该函数是 运行 来自不同的文件。它看起来像这样:
let childrenNodes = [
document.getElementsByClassName('menu')[0],
document.getElementsByClassName('dish-category')[0],
document.getElementsByClassName('dish-list')[0],
document.getElementsByClassName('dish')[0],
document.getElementsByClassName('dish')[1],
document.getElementsByClassName('dish')[2],
document.getElementsByClassName('dish')[3],
document.getElementsByClassName('dish')[4],
document.getElementsByClassName('price')[0],
document.getElementsByClassName('price')[1],
document.getElementsByClassName('price')[2],
document.getElementsByClassName('price')[3],
document.getElementsByClassName('price')[4]
];
const detectPlace = () => {
window.addEventListener('click', (e) => {
childrenNodes.some((node) => e.target === node) ? console.log('Clicked inside!') : console.log('Clicked outside!');
console.log(e.target);
});
}
你能告诉我为什么会这样吗?
您正在渲染 #placholder
的内容:
let placeholder = document.getElementById('placeholder');
placeholder.innerHTML = ReactDOMServer.renderToString(<Menu />);
ReactDOMServer.renderToString(...)
生成包含 HTML 的字符串。此字符串不包含任何 JavaScript,因此结果是非交互式的。
renderToString()
ReactDOMServer.renderToString(element)
Render a React element to its initial HTML. React will return an HTML
string. You can use this method to generate HTML on the server and
send the markup down on the initial request for faster page loads and
to allow search engines to crawl your pages for SEO purposes.
If you call ReactDOM.hydrate()
on a node that already has this
server-rendered markup, React will preserve it and only attach event
handlers, allowing you to have a very performant first-load
experience.
如果您想要交互式 DOM 结构,您应该使用正常的 ReactDOM.render(...)
方法来呈现您的组件。
let placeholder = document.getElementById('placeholder');
ReactDOM.render(<Menu />, placeholder);
// import { BrowserRouter as Router, Link } from 'react-router-dom';
// import { useState } from 'react';
const { BrowserRouter: Router, Link } = ReactRouterDOM;
const { useState } = React;
const Menu = () => {
let [pageNumber, switchPage] = useState(1);
let dish = {
categories: [
'proin blandit',
'suspendisse non',
'fermentum ultrices',
'volutpat vulputat'
],
names: [
['Sed fermentum', 'Sapien nec lobortis', 'Tristique in suspendisse', 'Pellentesque mattis elit', 'Vel interdum velit'],
['Nam nisi quam', 'Donec non viverra', 'Morbi suscipit mattis', 'Sed dignissim nisi', 'Aliquam vitae'],
['Curabitur ante mi', 'Nulla a felis', 'Donec porta convallis ', 'Vestibulum viverra ', 'Nullam viverra '],
['Vestibulum odio', 'Mauris neque ligula', 'Praesent iaculis nunc', 'Cras sollicitudin est', 'Class aptent taciti ']
],
prices: [
[13.99, 11.99, 15.99, 17.99, 21.99],
[22.99, 20.99, 18.99, 16.99, 24.99],
[11.99, 21.99, 31.99, 25.99, 15.99],
[6.99, 8.99, 10.99, 4.99, 8.99]
]
}
let iterator = Math.abs(pageNumber % 4);
let lineBreak = window.innerWidth <= 750 ? <br/> : undefined;
return (
<Router>
<section className='menu'>
<i className='fas fa-chevron-circle-left' id='menu-arrow-left' onClick={() => switchPage(pageNumber - 1)}></i>
<h1 className='dish-category'>You are viewing {dish.categories[iterator]}</h1>
<Link to='/home'><i className='fas fa-times'></i></Link>
<ul className='dish-list'>
<li className='dish'>{dish.names[iterator][0]} {lineBreak} <span className='price'>{dish.prices[iterator][0]} PLN</span></li>
<li className='dish'>{dish.names[iterator][1]} {lineBreak} <span className='price'>{dish.prices[iterator][1]} PLN</span></li>
<li className='dish'>{dish.names[iterator][2]} {lineBreak} <span className='price'>{dish.prices[iterator][2]} PLN</span></li>
<li className='dish'>{dish.names[iterator][3]} {lineBreak} <span className='price'>{dish.prices[iterator][3]} PLN</span></li>
<li className='dish'>{dish.names[iterator][4]} {lineBreak} <span className='price'>{dish.prices[iterator][4]} PLN</span></li>
</ul>
<i className='fas fa-chevron-circle-right' id='menu-arrow-right' onClick={() => switchPage(pageNumber + 1)}></i>
</section>
</Router>
)
}
let placeholder = document.getElementById('placeholder');
ReactDOM.render(<Menu />, placeholder);
<div id="placeholder"></div>
<link crossorigin rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" />
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script crossorigin src="https://unpkg.com/react-router-dom@5/umd/react-router-dom.js"></script>
我正在构建一个餐厅网站模板。在项目中,我确实有一个带有两个箭头按钮的模式框来更改页面。我通过 useState 跟踪 pageNumber
变量。不幸的是,该值永远不会更新,这会阻止页面更改。
这是 Menu.js 组件:
import { BrowserRouter as Router, Link } from 'react-router-dom';
import { useState } from 'react';
const Menu = () => {
let [pageNumber, switchPage] = useState(1);
let dish = {
categories: [
'proin blandit',
'suspendisse non',
'fermentum ultrices',
'volutpat vulputat'
],
names: [
['Sed fermentum', 'Sapien nec lobortis', 'Tristique in suspendisse', 'Pellentesque mattis elit', 'Vel interdum velit'],
['Nam nisi quam', 'Donec non viverra', 'Morbi suscipit mattis', 'Sed dignissim nisi', 'Aliquam vitae'],
['Curabitur ante mi', 'Nulla a felis', 'Donec porta convallis ', 'Vestibulum viverra ', 'Nullam viverra '],
['Vestibulum odio', 'Mauris neque ligula', 'Praesent iaculis nunc', 'Cras sollicitudin est', 'Class aptent taciti ']
],
prices: [
[13.99, 11.99, 15.99, 17.99, 21.99],
[22.99, 20.99, 18.99, 16.99, 24.99],
[11.99, 21.99, 31.99, 25.99, 15.99],
[6.99, 8.99, 10.99, 4.99, 8.99]
]
}
let iterator = Math.abs(pageNumber % 4);
let lineBreak = window.innerWidth <= 750 ? <br/> : undefined;
return (
<Router>
<section className='menu'>
<i className='fas fa-chevron-circle-left' id='menu-arrow-left' onClick={() => switchPage(pageNumber - 1)}></i>
<h1 className='dish-category'>You are viewing {dish.categories[iterator]}</h1>
<Link to='/home'><i className='fas fa-times'></i></Link>
<ul className='dish-list'>
<li className='dish'>{dish.names[iterator][0]} {lineBreak} <span className='price'>{dish.prices[iterator][0]} PLN</span></li>
<li className='dish'>{dish.names[iterator][1]} {lineBreak} <span className='price'>{dish.prices[iterator][1]} PLN</span></li>
<li className='dish'>{dish.names[iterator][2]} {lineBreak} <span className='price'>{dish.prices[iterator][2]} PLN</span></li>
<li className='dish'>{dish.names[iterator][3]} {lineBreak} <span className='price'>{dish.prices[iterator][3]} PLN</span></li>
<li className='dish'>{dish.names[iterator][4]} {lineBreak} <span className='price'>{dish.prices[iterator][4]} PLN</span></li>
</ul>
<i className='fas fa-chevron-circle-right' id='menu-arrow-right' onClick={() => switchPage(pageNumber + 1)}></i>
</section>
</Router>
)
}
export default Menu;
这是我切换模式可见性的方式:
const hideModal = (e) => {
e.preventDefault();
let placeholder = document.getElementById('placeholder');
placeholder.innerText = '';
placeholder.style.display = 'none';
let container = document.getElementById('container');
container.style.filter = '';
container.style.pointerEvents = 'auto';
}
const showModal = () => {
let placeholder = document.getElementById('placeholder');
placeholder.innerHTML = ReactDOMServer.renderToString(<Menu />);
placeholder.style.display = 'block';
let container = document.getElementById('container');
container.style.filter = 'blur(8px)';
container.style.pointerEvents = 'none';
}
这是App.js中对应的JSX代码:
<div id='placeholder'><Menu /> <Contact /></div>
另外,我写了一个检测点击位置的测试函数。当我在上面的示例中 运行 它时,我收到一条消息,指出我在模式框外单击,即使它是相反的。该函数是 运行 来自不同的文件。它看起来像这样:
let childrenNodes = [
document.getElementsByClassName('menu')[0],
document.getElementsByClassName('dish-category')[0],
document.getElementsByClassName('dish-list')[0],
document.getElementsByClassName('dish')[0],
document.getElementsByClassName('dish')[1],
document.getElementsByClassName('dish')[2],
document.getElementsByClassName('dish')[3],
document.getElementsByClassName('dish')[4],
document.getElementsByClassName('price')[0],
document.getElementsByClassName('price')[1],
document.getElementsByClassName('price')[2],
document.getElementsByClassName('price')[3],
document.getElementsByClassName('price')[4]
];
const detectPlace = () => {
window.addEventListener('click', (e) => {
childrenNodes.some((node) => e.target === node) ? console.log('Clicked inside!') : console.log('Clicked outside!');
console.log(e.target);
});
}
你能告诉我为什么会这样吗?
您正在渲染 #placholder
的内容:
let placeholder = document.getElementById('placeholder');
placeholder.innerHTML = ReactDOMServer.renderToString(<Menu />);
ReactDOMServer.renderToString(...)
生成包含 HTML 的字符串。此字符串不包含任何 JavaScript,因此结果是非交互式的。
renderToString()
ReactDOMServer.renderToString(element)
Render a React element to its initial HTML. React will return an HTML string. You can use this method to generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes.
If you call
ReactDOM.hydrate()
on a node that already has this server-rendered markup, React will preserve it and only attach event handlers, allowing you to have a very performant first-load experience.
如果您想要交互式 DOM 结构,您应该使用正常的 ReactDOM.render(...)
方法来呈现您的组件。
let placeholder = document.getElementById('placeholder');
ReactDOM.render(<Menu />, placeholder);
// import { BrowserRouter as Router, Link } from 'react-router-dom';
// import { useState } from 'react';
const { BrowserRouter: Router, Link } = ReactRouterDOM;
const { useState } = React;
const Menu = () => {
let [pageNumber, switchPage] = useState(1);
let dish = {
categories: [
'proin blandit',
'suspendisse non',
'fermentum ultrices',
'volutpat vulputat'
],
names: [
['Sed fermentum', 'Sapien nec lobortis', 'Tristique in suspendisse', 'Pellentesque mattis elit', 'Vel interdum velit'],
['Nam nisi quam', 'Donec non viverra', 'Morbi suscipit mattis', 'Sed dignissim nisi', 'Aliquam vitae'],
['Curabitur ante mi', 'Nulla a felis', 'Donec porta convallis ', 'Vestibulum viverra ', 'Nullam viverra '],
['Vestibulum odio', 'Mauris neque ligula', 'Praesent iaculis nunc', 'Cras sollicitudin est', 'Class aptent taciti ']
],
prices: [
[13.99, 11.99, 15.99, 17.99, 21.99],
[22.99, 20.99, 18.99, 16.99, 24.99],
[11.99, 21.99, 31.99, 25.99, 15.99],
[6.99, 8.99, 10.99, 4.99, 8.99]
]
}
let iterator = Math.abs(pageNumber % 4);
let lineBreak = window.innerWidth <= 750 ? <br/> : undefined;
return (
<Router>
<section className='menu'>
<i className='fas fa-chevron-circle-left' id='menu-arrow-left' onClick={() => switchPage(pageNumber - 1)}></i>
<h1 className='dish-category'>You are viewing {dish.categories[iterator]}</h1>
<Link to='/home'><i className='fas fa-times'></i></Link>
<ul className='dish-list'>
<li className='dish'>{dish.names[iterator][0]} {lineBreak} <span className='price'>{dish.prices[iterator][0]} PLN</span></li>
<li className='dish'>{dish.names[iterator][1]} {lineBreak} <span className='price'>{dish.prices[iterator][1]} PLN</span></li>
<li className='dish'>{dish.names[iterator][2]} {lineBreak} <span className='price'>{dish.prices[iterator][2]} PLN</span></li>
<li className='dish'>{dish.names[iterator][3]} {lineBreak} <span className='price'>{dish.prices[iterator][3]} PLN</span></li>
<li className='dish'>{dish.names[iterator][4]} {lineBreak} <span className='price'>{dish.prices[iterator][4]} PLN</span></li>
</ul>
<i className='fas fa-chevron-circle-right' id='menu-arrow-right' onClick={() => switchPage(pageNumber + 1)}></i>
</section>
</Router>
)
}
let placeholder = document.getElementById('placeholder');
ReactDOM.render(<Menu />, placeholder);
<div id="placeholder"></div>
<link crossorigin rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" />
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script crossorigin src="https://unpkg.com/react-router-dom@5/umd/react-router-dom.js"></script>