Я создаю сайт, на котором есть довольно много реагирующих компонентов, но это не SPA или полностью реагирующий сайт.Поэтому реагирующие компоненты попадают в страницы.У меня есть компонент наложения, который покрывает пользовательский интерфейс, когда открываются различные меню или выпадающие.У меня проблема в том, что я настроил свой контекст следующим образом:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export const OverlayContext = React.createContext();
export class OverlayProvider extends Component {
state = {
showOverlay: true,
test: 'default test value'
}
showHideOverlay = () => {
const visible = this.state.showOverlay;
this.setState({
showOverlay: visible ? false : true
});
}
render() {
return (
<OverlayContext.Provider value={{
state: this.state,
showHideOverlay: this.showHideOverlay
}}>
{this.props.children}
</OverlayContext.Provider>
);
}
}
OverlayProvider.propTypes = {
children: PropTypes.object
}
Затем я передаю этому провайдеру и потребителю 2 разных компонента:
- Мой оверлейный компонент
- Мой компонент MyAccount.
Вот они: Наложение:
import React from 'react';
import { render } from 'react-dom';
import PropTypes from 'prop-types'
import { OverlayProvider, OverlayContext } from './../contexts/OverlayContext';
// Styling
import styled from 'styled-components'
import { colors } from '../global-styled-constants/colors';
import { mixins } from '../global-styled-constants/mixins';
import { sizing } from '../global-styled-constants/sizing';
//Animations
import { fadeIn } from '../global-styled-constants/animations';
import { fadeOut } from '../global-styled-constants/animations';
const PageOverlay = styled.div`
${mixins.dimensions('100%', '100%')};
${mixins.position('fixed', '0', '0')};
display: block;
background: ${colors.red};
z-index: ${sizing.zIndex2};
${props => props.showOverlay ? `animation: ${fadeIn} 1s 0.3s both;` : `animation: ${fadeOut} 1.3s both;`}
`;
// the state containing the count will be fetched via the API and delivered to this component via redux
export const Overlay = () => {
return (
<OverlayProvider>
<OverlayContext.Consumer>
{(value) => (
<PageOverlay showOverlay={value.state.showOverlay}/>
)}
</OverlayContext.Consumer>
</OverlayProvider>
);
}
render(<Overlay/>, document.getElementById('react-overlay'))
Overlay.propTypes = {
showOverlay: PropTypes.bool.isRequired
}
MyAccount:
import React, { Component, Fragment } from 'react';
import { OverlayProvider, OverlayContext } from '../../contexts/OverlayContext';
// Styling
import styled from 'styled-components'
import { colors } from '../../global-styled-constants/colors'
import { mixins } from '../../global-styled-constants/mixins'
import { sizing } from '../../global-styled-constants/sizing'
import { type } from '../../global-styled-constants/typography'
// import { mq } from '../../global-styled-constants/mediaQueries';
const Wrapper = styled.div`
position: relative;
`;
const List = styled.ul`
${mixins.dimensions('195px', 'auto')};
position: absolute;
background: ${colors.lightSmoke};
z-index: 10;
top: 38px;
padding: 15px;
${props => props.showDropdown ? `display: block;` : `display: none`};
`;
const Item = styled.li`
padding: 15px 0;
a {
font-size: ${sizing.scaleh10};
font-family: ${type.fsSanSerif};
font-weight: ${sizing.fontWeightBold};
font-style: normal;
text-decoration: none;
}
&:hover {
cursor: pointer;
color: ${colors.orange};
}
`;
const Trigger = styled.li`
${mixins.flex('center')};
height: 38px;
font-size: ${sizing.scaleh10};
padding: 0 20px;
position: relative;
color: ${colors.anotherGrey};
font-family: ${type.fsSanSerif};
font-weight: ${sizing.fontWeightBold};
font-style: normal;
text-decoration: none;
cursor: pointer;
${props => props.showDropdown && `background: ${colors.lightSmoke}; color: ${colors.orange}`};
`;
const accountData = {
"loggedOut": {
"displayCTA": "My Account",
"links": [
{
"displayName": "Sign In",
"link": "www.google.com"
},
{
"displayName": "Sign up / Join",
"link": "www.google.com"
},
{
"displayName": "Register Products",
"link": "www.google.com"
},
{
"displayName": "Subscribe to Newsletter",
"link": "www.google.com"
}
]
},
"loggedIn": {
"displayCTA": "{userEmail}",
"links": [
{
"displayName": "My Products",
"link": "www.google.com"
},
{
"displayName": "My Wishlist",
"link": "www.google.com"
},
{
"displayName": "My Orders",
"link": "www.google.com"
},
{
"displayName": "My Profile",
"link": "www.google.com"
},
{
"displayName": "Sign Out",
"link": "www.google.com"
},
{
"displayName": "Register Products",
"link": "www.google.com"
},
{
"displayName": "Newsletter Sign up",
"link": "www.google.com"
}
]
}
}
export default class MyAccount extends Component {
constructor(props) {
super(props);
this.state = {
showDropdown: false,
loggedIn: false
}
}
hoverAwakeMenu = () => {
this.setState({
showDropdown: true
})
}
mouseLeft = () => {
this.setState({
showDropdown: false
});
}
render() {
const { showDropdown, loggedIn } = this.state;
const data = loggedIn ? accountData.loggedIn.links : accountData.loggedOut.links;
const displayCTA = loggedIn ? accountData.loggedIn.displayCTA : accountData.loggedOut.displayCTA;
const itemsList = data.map((item, i) => <Item key={i}><a href={item.link}>{item.displayName}</a></Item>);
return (
<OverlayProvider>
<Fragment>
<Wrapper onMouseLeave={this.mouseLeft}>
<OverlayContext.Consumer>
{(value) => (
<Trigger showDropdown={showDropdown} onMouseEnter={(e) => {this.hoverAwakeMenu(e); value.showHideOverlay(e);}}>{displayCTA}</Trigger>
)}
</OverlayContext.Consumer>
<List showDropdown={showDropdown}>
{itemsList}
</List>
</Wrapper>
</Fragment>
</OverlayProvider>
);
}
}
Когда я вызываю value.showHideOverlay(е);из MyAccount.js он обновляет состояние в контексте, но затем не пересылает это изменение в Overlay.js, в котором стили «showOverlay» пропа основаны на этом логическом значении.Если я добавлю в свой аккаунт тестовую опору, он получит изменение.То же самое происходит, если я запускаю событие из Overlay.js.Реквизиты внутри оверлея обновляются с того состояния в контексте, но не в MyAccount.js
Я предполагаю, что я делаю что-то не так с несколькими поставщиками, возможно, но у меня сложилось впечатление, что несколько поставщиков были абсолютно в порядкеAPI реагирующего контекста.
Любое направление приветствуется!