- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我继承了一个react/node/prismic应用程序,我们需要更新prismic-reactjs包,这导致需要更新其他一些包——总的来说,我们改变了:
prismic-reactjs:0.2.0 → 1.1.0
react :15.6.1 → 16.0.0
webpack:3.12.0 → 4.39.2
react-dom:15.6.1 → 16.0.0
react-router-dom:4.1.2 → 5.0.1
extract-text-webpack-plugin(已弃用)→ mini-css-extract-plugin
然后删除了“withRouter()”的一个使用,因为启动本地服务器时出现了新错误(但我在另一个分支中确认,单独进行该编辑不会产生下面的症状)
上下文:我们有一个 personMap,它显示一组人的图标,您单击其中一个即可打开 PersonMapStory 模式,该模式显示该人的故事,然后链接到该人的其他人底部的列表。如果您向下滚动并单击其中一个链接,顶部的故事将相应替换(用新人的故事),下面列出的是其他所有人。在代码中,这些底部链接的按钮 onClick 行为是 setActivePerson() 给这个新人。
新错误:在这个新分支中,当我打开故事模式并将鼠标悬停在页面上然后再次返回时,我们会重复与 onMouseEnter 和 onMouseEnter 关联的 setQueuedUpPerson 和 setNoQueuedUpPerson 调用onMouseLeave。 (在以前的/生产代码中不会发生)。它导致了下游问题,我正在尝试找出如何防止这种情况发生。
更多信息:我已经看到 propagation issue解决方案是传递事件并在适当的方法中调用 stopPropagation,这似乎是同一类型的行为。有没有办法做同样的事情,让它在模式启动时停止监听悬停行为?
更新了 PersonMap.js(来自第一个建议的答案):
import Modal from 'react-modal'
import PropTypes from 'prop-types'
import React from 'react'
import PersonMapPoint from './PersonMapPoint'
import PersonMapStory from './PersonMapStory'
import PersonMapCallout from './PersonMapCallout'
import PersonMapLocator from './PersonMapLocator'
import PersonMapBackground from './PersonMapBackground'
const CUSTOM_STYLES = {
content: {
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: '#fff',
zIndex: 10,
border: 'none'
}
}
class PersonMap extends React.Component {
constructor(props) {
super(props)
this.setActivePerson = this.setActivePerson.bind(this)
this.setNoActivePerson = this.setNoActivePerson.bind(this)
this.setQueuedUpPerson = this.setQueuedUpPerson.bind(this)
this.setNoQueuedUpPerson = this.setNoQueuedUpPerson.bind(this)
this.checkBlurEvent = this.checkBlurEvent.bind(this)
this.setIsDesktop = this.setIsDesktop.bind(this)
this.checkHasBeenScrolledTo = this.checkHasBeenScrolledTo.bind(this)
this.setTopRef = this.setTopRef.bind(this)
this.handleKeyPress = this.handleKeyPress.bind(this)
this.state = {
activePerson: null,
queuedUpPerson: null,
scrollPos: 0,
isDesktop: false,
hasBeenScrolledTo: false,
lastQueuedPerson: null
}
}
componentDidMount() {
this.setIsDesktop()
this.checkHasBeenScrolledTo()
window.addEventListener('resize', this.setIsDesktop)
window.addEventListener('scroll', this.checkHasBeenScrolledTo)
}
componentWillUnmount() {
window.removeEventListener('resize', this.setIsDesktop)
window.removeEventListener('scroll', this.checkHasBeenScrolledTo)
}
setTopRef(element) {
this.topRef = element
}
setActivePerson(personName) {
this.setState({
activePerson: personName,
scrollPos: window.scrollY
})
}
setNoActivePerson() {
this.setState({
queuedUpPerson: this.state.activePerson,
activePerson: null
}, () => {
setTimeout(() => {
window.scrollTo(0, this.state.scrollPos)
}, 50)
})
}
setQueuedUpPerson(e, personName) {
this.setState({
queuedUpPerson: personName,
lastQueuedPerson: personName
})
e.stopPropagation()
}
setNoQueuedUpPerson(e) {
this.setState({
queuedUpPerson: null
})
e.stopPropagation()
}
handleKeyPress(e, name) {
if (e.key !== ' ' && e.key !== 'Enter') {
return
}
this.setActivePerson(name)
}
checkBlurEvent(e) {
if (Array.from(e.currentTarget.childNodes[0].childNodes).includes(e.relatedTarget)) {
return
}
this.setNoQueuedUpPerson(e)
}
render() {
return (
<section className="slice-area person-map CONSTRAIN">
<div className="person-map-headers">
<div className="person-map-headers-inner">
<h1 className="person-map-title">
{this.props.title}
</h1>
<p className="person-map-disclaimer">
{this.props.disclaimer}
</p>
</div>
</div>
{
!this.state.isDesktop &&
<div className="person-map-graphic" ref={this.setTopRef}>
{
this.props.personStories.map(person => (
<PersonMapLocator
x={person.x}
y={person.y}
key={person.name}
>
<PersonMapPoint name={person.name}/>
</PersonMapLocator>
))
}
<PersonMapBackground isVisible={this.state.hasBeenScrolledTo} />
</div>
}
<div
className={`person-map-list-wrap${ this.state.isDesktop ? ' --desktop' : '' }`}
ref={this.state.isDesktop && this.setTopRef}
>
{ this.state.isDesktop &&
<PersonMapBackground isVisible={this.state.hasBeenScrolledTo}/>
}
<ul className="person-map-list">
{
this.props.personStories.map((person) => {
const thisPersonIsQueued = this.state.queuedUpPerson === person.name
const thisPersonIsActive = this.state.activePerson === person.name
const thisPersonWasLastQueued = this.state.lastQueuedPerson === person.name
return (
<li
key={person.name} className={`person-map-list-item${thisPersonWasLastQueued ? ' --active' : ''}`}
onMouseEnter={this.state.isDesktop ? (e) => this.setQueuedUpPerson(e, person.name) : null}
onMouseLeave={this.state.isDesktop ? this.setNoQueuedUpPerson : null}
onFocus={this.state.isDesktop ? (e) => this.setQueuedUpPerson(e, person.name) : null}
onBlur={this.state.isDesktop ? this.checkBlurEvent : null}
onClick={thisPersonIsQueued || !this.state.isDesktop ? () => this.setActivePerson(person.name) : null}
onKeyPress={(e) => this.handleKeyPress(e, person.name)}
>
{
this.state.isDesktop ?
<PersonMapLocator
x={person.x}
y={person.y}
>
<PersonMapPoint
name={person.name}
isInteractive
isActive={thisPersonIsQueued}
imageUrl={person.photo_url}
/>
<PersonMapCallout
name={person.name}
photo={person.photo_url}
isOpen={thisPersonIsQueued}
isDesktop
/>
</PersonMapLocator> :
<PersonMapCallout
name={person.name}
photo={person.photo_url}
/>
}
<Modal
isOpen={thisPersonIsActive}
onRequestClose={this.setNoActivePerson}
style={CUSTOM_STYLES}
>
<PersonMapStory
name={person.name}
photo={person.photo_url}
story={person.story}
setNoActivePerson={this.setNoActivePerson}
setActivePerson={this.setActivePerson}
isActive={thisPersonIsActive}
otherPersons={this.props.personStories.filter((item) => item.name !== person.name).map((item) => ({ name: item.name, photo: item.photo_url }))}
isDesktop={this.state.isDesktop}
/>
</Modal>
</li>
)
})
}
</ul>
</div>
</section>
)
}
}
PersonMap.propTypes = {
title: PropTypes.string,
disclaimer: PropTypes.string,
personStories: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
photo_url: PropTypes.string,
x: PropTypes.number,
y: PropTypes.number,
story: PropTypes.shape({
title: PropTypes.string,
link: PropTypes.string,
content: PropTypes.arrayOf(PropTypes.shape({
question: PropTypes.string,
answer: PropTypes.string
}))
})
}))
}
export default PersonMap
原始 PersonMap.js:
import Modal from 'react-modal'
import PropTypes from 'prop-types'
import React from 'react'
import PersonMapPoint from './PersonMapPoint'
import PersonMapStory from './PersonMapStory'
import PersonMapCallout from './PersonMapCallout'
import PersonMapLocator from './PersonMapLocator'
import PersonMapBackground from './PersonMapBackground'
const CUSTOM_STYLES = {
content: {
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: '#fff',
zIndex: 10,
border: 'none'
}
}
class PersonMap extends React.Component {
constructor(props) {
super(props)
this.setActivePerson = this.setActivePerson.bind(this)
this.setNoActivePerson = this.setNoActivePerson.bind(this)
this.setQueuedUpPerson = this.setQueuedUpPerson.bind(this)
this.setNoQueuedUpPerson = this.setNoQueuedUpPerson.bind(this)
this.checkBlurEvent = this.checkBlurEvent.bind(this)
this.setIsDesktop = this.setIsDesktop.bind(this)
this.checkHasBeenScrolledTo = this.checkHasBeenScrolledTo.bind(this)
this.setTopRef = this.setTopRef.bind(this)
this.handleKeyPress = this.handleKeyPress.bind(this)
this.state = {
activePerson: null,
queuedUpPerson: null,
scrollPos: 0,
isDesktop: false,
hasBeenScrolledTo: false,
lastQueuedPerson: null
}
}
componentDidMount() {
this.setIsDesktop()
this.checkHasBeenScrolledTo()
window.addEventListener('resize', this.setIsDesktop)
window.addEventListener('scroll', this.checkHasBeenScrolledTo)
}
componentWillUnmount() {
window.removeEventListener('resize', this.setIsDesktop)
window.removeEventListener('scroll', this.checkHasBeenScrolledTo)
}
setTopRef(element) {
this.topRef = element
}
setActivePerson(personName) {
this.setState({
activePerson: personName,
scrollPos: window.scrollY
})
event.stopPropagation()
}
setNoActivePerson() {
this.setState({
queuedUpPerson: this.state.activePerson,
activePerson: null
}, () => {
setTimeout(() => {
window.scrollTo(0, this.state.scrollPos)
}, 50)
})
}
setQueuedUpPerson(personName) {
this.setState({
queuedUpPerson: personName,
lastQueuedPerson: personName
})
}
setNoQueuedUpPerson() {
this.setState({
queuedUpPerson: null
})
event.stopPropagation()
}
handleKeyPress(e, name) {
if (e.key !== ' ' && e.key !== 'Enter') {
return
}
this.setActivePerson(name)
}
checkBlurEvent(e) {
if (Array.from(e.currentTarget.childNodes[0].childNodes).includes(e.relatedTarget)) {
return
}
this.setNoQueuedUpPerson()
}
render() {
return (
<section className="slice-area person-map CONSTRAIN">
<div className="person-map-headers">
<div className="person-map-headers-inner">
<h1 className="person-map-title">
{this.props.title}
</h1>
<p className="person-map-disclaimer">
{this.props.disclaimer}
</p>
</div>
</div>
<div
className={`person-map-list-wrap${ this.state.isDesktop ? ' --desktop' : '' }`}
ref={this.state.isDesktop && this.setTopRef}
>
{ this.state.isDesktop &&
<PersonMapBackground isVisible={this.state.hasBeenScrolledTo}/>
}
<ul className="person-map-list">
{
this.props.personStories.map((person) => {
const thisPersonIsQueued = this.state.queuedUpPerson === person.name
const thisPersonIsActive = this.state.activePerson === person.name
const thisPersonWasLastQueued = this.state.lastQueuedPerson === person.name
return (
<li
key={person.name} className={`person-map-list-item${thisPersonWasLastQueued ? ' --active' : ''}`}
onMouseEnter={this.state.isDesktop ? () => this.setQueuedUpPerson(person.name) : null}
onMouseLeave={this.state.isDesktop ? this.setNoQueuedUpPerson : null}
onFocus={this.state.isDesktop ? () => this.setQueuedUpPerson(person.name) : null}
onBlur={this.state.isDesktop ? this.checkBlurEvent : null}
onClick={thisPersonIsQueued || !this.state.isDesktop ? () => this.setActivePerson(person.name) : null}
onKeyPress={(e) => this.handleKeyPress(e, person.name)}
>
{
<PersonMapLocator
x={person.x}
y={person.y}
>
}
<Modal
isOpen={thisPersonIsActive}
onRequestClose={this.setNoActivePerson}
style={CUSTOM_STYLES}
>
<PersonMapStory
name={person.name}
photo={person.photo_url}
story={person.story}
setNoActivePerson={this.setNoActivePerson}
setActivePerson={this.setActivePerson}
isActive={thisPersonIsActive}
otherPersons={this.props.personStories.filter((item) => item.name !== person.name).map((item) => ({ name: item.name, photo: item.photo_url }))}
isDesktop={this.state.isDesktop}
/>
</Modal>
</li>
)
})
}
</ul>
</div>
</section>
)
}
}
PersonMap.propTypes = {
title: PropTypes.string,
disclaimer: PropTypes.string,
personStories: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
photo_url: PropTypes.string,
x: PropTypes.number,
y: PropTypes.number,
story: PropTypes.shape({
title: PropTypes.string,
link: PropTypes.string,
content: PropTypes.arrayOf(PropTypes.shape({
question: PropTypes.string,
answer: PropTypes.string
}))
})
}))
}
export default PersonMap
PersonMapStory.js:
import PropTypes from 'prop-types'
import React from 'react'
import PersonMapPerson from './PersonMapPerson'
class PersonMapStory extends React.Component {
constructor(props) {
console.log("PersonMapStory constructor")
super(props)
this.deactivateThisPerson = this.deactivateThisPerson.bind(this)
this.check = 0
}
deactivateThisPerson(backPressed = false) {
if (!backPressed) {
history.back()
}
console.log("Set no active person ")
this.props.setNoActivePerson()
}
setActivePerson(name) {
this.props.setActivePerson(name)
event.stopPropagation()
}
componentDidMount() {
const loc = window.location.pathname.substr(1)
this.setState({ location: loc })
const openState = { modalOpen: true }
history.pushState(openState, 'signup-open', loc)
}
render() {
return (
<div className={`person-map-story${this.props.isActive ? ' --active' : ''}${this.props.isDesktop ? ' --desktop' : ''}`}>
<h2 className="person-map-story-title">
{ this.props.story.title }
</h2>
<button className="person-map-story-close-button" onClick={() => {this.deactivateThisPerson(false)}}>
<span className="person-map-story-close-button-text">
Close Story
</span>
</button>
<div className="person-map-story-body">
<span className="person-map-story-person-wrap">
<PersonMapPerson
photo={this.props.photo}
name={this.props.name}
/>
</span>
{
this.props.story.content.map((section) => {
if (section) {
return (
<div key={section.question}>
<h3 className="person-map-story-question">{section.question}</h3>
<p className="person-map-story-answer">
{section.answer}
</p>
</div>
)
}
})
}
{
this.props.story.link &&
<a href={this.props.story.link}
target="_blank"
className="person-map-story-more-link header-and-text-link"
> Read More Stories
</a>
}
<ul className="person-map-story-other-list">
{
this.props.otherPersons.map((person) => (
<li
key={person.name}
className="person-map-story-other-list-item"
>
<button className="person-map-story-other-button" onClick={() => this.setActivePerson(person.name)}>
<PersonMapPerson
name={person.name}
photo={person.photo}
ctaText="View their story"
/>
</button>
</li>
))
}
</ul>
</div>
</div>
)
}
}
PersonMapStory.propTypes = {
name: PropTypes.string,
photo: PropTypes.string,
story: PropTypes.shape({
title: PropTypes.string,
link: PropTypes.string,
content: PropTypes.arrayOf(PropTypes.shape({
question: PropTypes.string,
answer: PropTypes.string
}))
}),
setNoActivePerson: PropTypes.func,
setActivePerson: PropTypes.func,
isActive: PropTypes.bool,
otherPersons: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
photo: PropTypes.string
})),
isDesktop: PropTypes.bool
}
export default PersonMapStory
最佳答案
更新(如下所示不起作用):
您能否关闭处于 state
状态的 activePerson
来判断模式是否打开,这意味着您不需要 setQueuedUpPerson
或 setNoQueuedUpPerson
调用?要么像这样改变它们:
setQueuedUpPerson(e, personName) {
if(!this.state.activePerson) {
this.setState({
queuedUpPerson: personName,
lastQueuedPerson: personName
})
}
e.stopPropagation()
}
setNoQueuedUpPerson(e) {
if(!this.state.activePerson) {
this.setState({
queuedUpPerson: null
})
}
e.stopPropagation()
}
或者如果存在 activePerson
,则将 onMouseEnter
和 onMouseLeave
事件设为 null?
你应该能够改变
onMouseEnter={this.state.isDesktop ? () => this.setQueuedUpPerson(person.name) : null}
至
onMouseEnter={this.state.isDesktop ? (e) => this.setQueuedUpPerson(e,person.name) : null}
然后像之前的问题一样访问该事件以停止传播:
setQueuedUpPerson(event, personName) {
this.setState({
queuedUpPerson: personName,
lastQueuedPerson: personName
})
event.stopPropagation()
}
使用 onMouseLeave
时,您只需将 event
参数添加到您的函数中,因为它已经公开,因为您直接传递函数引用,而不是调用它来自匿名函数,例如 onMouseEnter
:
setNoQueuedUpPerson(event) {
this.setState({
queuedUpPerson: null
})
event.stopPropagation()
}
关于javascript - 自从更新react-dom和react-router-dom包: behaviors executing additional times,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58565713/
作为一个小项目(没有什么关键任务),我决定尝试用 C# 编写 GOST 28147-89 的实现。但是,在阅读 RFC 5830 时(定义 GOST 28147-89 的信息),我注意到了这一点。 (
我在 Android JNI 上使用 Neon 实现了一个算法。当我想将向量相加时,我注意到有两种类型的方法,但我看不出其中的区别。 // pairwise addition int8x8_t vpa
我想知道为什么 STL 没有重载它们的算法函数,这样我就可以通过简单地提供一个容器而不是采用更冗长的方式来传递开始 + 结束迭代器来调用它们。我当然理解为什么我们还想使用迭代器对来处理容器/数组的子序
我想知道为什么 STL 不会重载它们的算法函数,这样我就可以通过简单地提供一个容器而不是采用更冗长的方式来传递 begin + end 迭代器来调用它们。我当然理解为什么我们还想使用迭代器对来处理容器
假设我有两个模块 - Module1、Module2。 每个模块在 Visual Studio 中都有自己的项目。 如何使用“附加模块依赖项”或“附加 BMI 目录”设置将模块 2 导入模块 1? 问
我有一个问题 df = data.frame(col1 = c("A", "B", "C", "A", "A", "B"), col2 = c(0.2, 0.2, 0.6, 1, 0.8, 0.2),
在sencha touch中,我有一个如下声明的轮播: ajaxNav = new Ext.Panel({ scroll: 'vertical', cls: 'card1 dem
我有一个开始日期,如下所示: var beginDate = "29/04/2015"; var beginHour = "13:32"; 我有一些持续时间变量: var hourDuration =
我一直在以一种相当粗糙的函数式方式进行一些动态系统模拟,目前正试图弄清楚 cpp 对象可以为我的代码带来什么。更具体地说,我在考虑以下结构: 我想通过一个抽象类来指定动力系统,比如“DynSys”,用
我想知道是否有办法强制将图像加载为 8U。我在 OpenCV 文档中看到您可以指定是将图像加载为单 channel 还是三 channel ,但没有提及颜色深度。有什么建议吗? 感谢您的帮助!!! :
题目地址:https://leetcode.com/problems/additive-number/description/ 题目描述: Additive number is a string
我已经使用 react-leaflet 有一段时间了,几周后我删除了 node_modules 中的文件并重新安装了它们,我根本没有接触 react-leaflet 版本,但是当我尝试运行时该项目,它
令我惊讶的是,我发现在 TCanvas 上重复渲染文本在某种程度上是“附加的”。我意识到设置 Canvas.Brush.Style:=bsClear 是问题的原因,但我确实需要透明且重复地渲染文本(即
我有一个 pdf 文件,其中包含“UniCNS-UCS2-H”字体,我尝试了 pdfbox 和 pdfrenderer,它们都抛出异常:“UniCNS-UCS2-H”的未知编码 这个字体包含在一个字体
我有一个大多数用户只会使用一次的 Facebook 应用程序。在进入 Facebook 工作流程之前,用户表明他们是否希望自己的墙被写入。基于此,我要么请求 publish_stream 许可,要么不
我正在尝试使用 CodeIgnitor 在 php、mysql 中制作标记表。我已经使用XAMPP并创建了一个数据库。用于存储每条记录。正在从数据库中检索数据,插入的新记录已成功编辑 但问题在于检索总
是否可以为 AppStore 应用审核提供额外的文件? 我们正在开发一个与 SAP 服务器通信的应用程序。为了审查该应用程序,我们设置了一个可供 Apple 访问的测试服务器。但是该服务器上的证书是自
enter image description here 我正在尝试设置我的函数并执行一些重载操作,以便我可以 +、-、==、* 两个矩阵。我在第一次操作重载时遇到了一个问题:加法。 我的程序一直有效
我正在尝试制作一个可以执行各种算术函数的基本计算器,从加法开始!现在我已经弄清楚了它的基本逻辑,但我不确定如何获取两个输入并将其打印出来! #include int main() { cha
这个问题在这里已经有了答案: Showing a Windows form on a secondary monitor? (9 个回答) 关闭 9 年前。 我有一个应用程序,其中有一个我想在第二个
我是一名优秀的程序员,十分优秀!