如何设置反应模式以从应用程序中的任何位置打开?
How can I set up a react modal to open from anywhere in the app?
我对 React 比较陌生,但我正在尝试设置一个可以从任何地方打开的模式。这是我尝试打开模式的方式:
class SearchResults extends React.Component {
static propTypes = {
status: React.PropTypes.string.isRequired,
results: React.PropTypes.array.isRequired,
onResultClick: React.PropTypes.func.isRequired
}
constructor(props) {
super(props)
}
onUploadButtonClick() {
console.log('here');
}
render () {
const uploadButtonFn = this.onUploadButtonClick
let childElements = [];
childElements.unshift((
<div className="upload-button-wrapper" key="upload-button">
<button type="button" className="upload-button" onClick={uploadButtonFn}><span>+</span> Upload Your Vidy</button>
</div>
))
return (
<div className='search-results'>
<div className='inner-content'>
{(() => {
if (this.props.status === 'fetching') {
return <h1>searching</h1>
}
if (this.props.status === 'ready') {
return (
<Masonry
className={'my-gallery-class'} // default ''
elementType={'div'} // default 'div'
disableImagesLoaded={false} // default false
updateOnEachImageLoad={false} // default false and works only if disableImagesLoaded is false
>
{childElements}
</Masonry>
)
}
})()}
</div>
<GetMoreResult />
</div>
)
}
}
export default SearchResults
这就是我尝试打开模式的方式。我几乎肯定有更好的方法。我想我正在使用 redux
。我继承了这个项目,所以我可能不会做任何事情。
如有任何帮助,我们将不胜感激。我想我需要在我的主布局中包含模式,但我该如何触发它?
不确定您的代码是如何工作的,connect()
在哪里?在这里的任何地方都是我认为你想要使用 redux 的东西。这只是一个示例,因此您可以了解我们如何显示来自任何其他组件的模态,即使它不相关:
//action
const toggleModal = (isVisible) => ({
type: "TOGGLE_MODAL",
isVisible: isVisible
});
//reducer
export default (state={}, action) => {
switch (action.type) {
case "TOGGLE_MODAL":
return {...state, isVisible: action.isVisible}
default:
return state;
}
}
//connect() allows us to dispatch an action
class RandomClassElseWhereInApp extends connect()(React.Component {
constructor(props) {
super(props)
}
OpenModal = () => this.props.dispatch(toggleModal(true))
render () {
return (
);
}
})
//Gives us access to the store
const mapStateToProps = (state) => ({
state.Modal.isVisible
});
//This is a smart component
class Modal extends connect(mapStateToProps)(React.Component {
constructor(props) {
super(props)
}
componentWillReceiveProps(nextProps) {
//Empty string for display sets it to original value
const display = "" ? this.props.isVisible : "none";
this.setState({myModalStyle: {display: display}});
}
render () {
return (
<Popup style={this.state.myModalStyle}/>
);
}
})
//This is a dumb component
const Popup = ({style}) => (
<div class="popup" style={style} />
);
我们的解决方案是这样的:如果你正在使用 redux 和 react-redux。
首先,制作一些动作创建器和一些 redux 状态来控制显示哪个模式。
// modal-action-reducer.js
export const ActionTypes = {
CLOSE_MODAL: 'CLOSE_MODAL',
OPEN_MODAL: 'OPEN_MODAL'
};
export const ActionCreators = {
OpenModal = id => ({ type: ActionTypes.OPEN_MODAL, payload: { id } }),
CloseModal: () => ({ type: ActionTypes.CLOSE_MODAL })
};
// this part of the state will be on something like `state.visibleModal`
export const reducer = (state = null, action) => {
switch (action.type) {
case ActionTypes.OPEN_MODAL:
return action.payload.id;
case ActionTypes.CLOSE_MODAL:
return null;
default:
return state;
}
};
然后制作一个高阶组件来装饰您的实际模态UI。
// ModalDecorator.jsx
import React from 'react';
import {connect} from 'react-redux';
import {ActionCreators} from './modal-action-reducer.js';
export default function ModalDecorator (modalId) {
return function (WrappedModalComponent) {
class WrapperComponent extends React.Component {
render () {
const {isVisible, ...otherProps} = this.props;
return isVisible
? <WrappedModalComponent {...otherProps} />
: <div style={{ display: 'none' }} >;
}
}
// get whether this modal is visible by checking the state from the reducer against the modal id
const mapStateToProps = state => ({
isVisible: state.visibleModal === modalId
});
// for convenience we can add a closeModal prop to all modals
const mapDispatchToProps = dispatch => ({
closeModal: () => dispatch(ActionCreators.CloseModal());
});
return connect(mapStateToProps, mapDispatchToProps)(WrapperComponent);
}
}
然后在你的实际模式中:
// MyModal.jsx
import React from 'react';
import ModalDecorator from './ModalDecorator.jsx';
class MyModal extends React.Component {
render () { /* Do your thing here */ }
}
export default ModalDecorator('my-modal-id')(MyModal);
这里需要注意的是,所有模态都必须在某处呈现,因此请为它们制作一个基本容器:
// ModalDeclarations.jsx
import MyModal from './MyModal.jsx';
import SomeOtherModal from './SomeOtherModaal.jsx';
const ModalDeclarations = () => (
<div>
<MyModal/>
<SomeOtherModal/>
</div>
);
export default ModalDeclarations;
并在 App.jsx
import React from 'react'
import ModalDeclarations from './ModalDeclarations.jsx';
export default class App extends React.Component {
render () {
return (
<div>
{/* Other bits of your app here */}
<ModalDeclarations />
</div>
);
}
}
最后,我们可以在任何地方使用 OpenModal 动作创建器来打开任何模式。这是一个按钮,它将使用它的道具中的 modalId 打开模式。
// ModalButton.jsx
import React from 'react';
import {connect} from 'react-redux';
import {ActionCreators} from './modal-action-reducer.js';
const mapDispatchToProps = (dispatch, ownProps) => ({
openModal: () => dispatch(ActionCreators.OpenModal(ownProps.modalId))
});
class ModalButton extends React.Component {
render () {
return (
<div onClick={this.props.openModal} >
{this.props.children}
</div>
)
}
}
export default connect(null, mapDispatchToProps)(ModalButton);
ModalButton.propTypes = {
modalId: React.PropTypes.string.isRequired
};
我对 React 比较陌生,但我正在尝试设置一个可以从任何地方打开的模式。这是我尝试打开模式的方式:
class SearchResults extends React.Component {
static propTypes = {
status: React.PropTypes.string.isRequired,
results: React.PropTypes.array.isRequired,
onResultClick: React.PropTypes.func.isRequired
}
constructor(props) {
super(props)
}
onUploadButtonClick() {
console.log('here');
}
render () {
const uploadButtonFn = this.onUploadButtonClick
let childElements = [];
childElements.unshift((
<div className="upload-button-wrapper" key="upload-button">
<button type="button" className="upload-button" onClick={uploadButtonFn}><span>+</span> Upload Your Vidy</button>
</div>
))
return (
<div className='search-results'>
<div className='inner-content'>
{(() => {
if (this.props.status === 'fetching') {
return <h1>searching</h1>
}
if (this.props.status === 'ready') {
return (
<Masonry
className={'my-gallery-class'} // default ''
elementType={'div'} // default 'div'
disableImagesLoaded={false} // default false
updateOnEachImageLoad={false} // default false and works only if disableImagesLoaded is false
>
{childElements}
</Masonry>
)
}
})()}
</div>
<GetMoreResult />
</div>
)
}
}
export default SearchResults
这就是我尝试打开模式的方式。我几乎肯定有更好的方法。我想我正在使用 redux
。我继承了这个项目,所以我可能不会做任何事情。
如有任何帮助,我们将不胜感激。我想我需要在我的主布局中包含模式,但我该如何触发它?
不确定您的代码是如何工作的,connect()
在哪里?在这里的任何地方都是我认为你想要使用 redux 的东西。这只是一个示例,因此您可以了解我们如何显示来自任何其他组件的模态,即使它不相关:
//action
const toggleModal = (isVisible) => ({
type: "TOGGLE_MODAL",
isVisible: isVisible
});
//reducer
export default (state={}, action) => {
switch (action.type) {
case "TOGGLE_MODAL":
return {...state, isVisible: action.isVisible}
default:
return state;
}
}
//connect() allows us to dispatch an action
class RandomClassElseWhereInApp extends connect()(React.Component {
constructor(props) {
super(props)
}
OpenModal = () => this.props.dispatch(toggleModal(true))
render () {
return (
);
}
})
//Gives us access to the store
const mapStateToProps = (state) => ({
state.Modal.isVisible
});
//This is a smart component
class Modal extends connect(mapStateToProps)(React.Component {
constructor(props) {
super(props)
}
componentWillReceiveProps(nextProps) {
//Empty string for display sets it to original value
const display = "" ? this.props.isVisible : "none";
this.setState({myModalStyle: {display: display}});
}
render () {
return (
<Popup style={this.state.myModalStyle}/>
);
}
})
//This is a dumb component
const Popup = ({style}) => (
<div class="popup" style={style} />
);
我们的解决方案是这样的:如果你正在使用 redux 和 react-redux。
首先,制作一些动作创建器和一些 redux 状态来控制显示哪个模式。
// modal-action-reducer.js
export const ActionTypes = {
CLOSE_MODAL: 'CLOSE_MODAL',
OPEN_MODAL: 'OPEN_MODAL'
};
export const ActionCreators = {
OpenModal = id => ({ type: ActionTypes.OPEN_MODAL, payload: { id } }),
CloseModal: () => ({ type: ActionTypes.CLOSE_MODAL })
};
// this part of the state will be on something like `state.visibleModal`
export const reducer = (state = null, action) => {
switch (action.type) {
case ActionTypes.OPEN_MODAL:
return action.payload.id;
case ActionTypes.CLOSE_MODAL:
return null;
default:
return state;
}
};
然后制作一个高阶组件来装饰您的实际模态UI。
// ModalDecorator.jsx
import React from 'react';
import {connect} from 'react-redux';
import {ActionCreators} from './modal-action-reducer.js';
export default function ModalDecorator (modalId) {
return function (WrappedModalComponent) {
class WrapperComponent extends React.Component {
render () {
const {isVisible, ...otherProps} = this.props;
return isVisible
? <WrappedModalComponent {...otherProps} />
: <div style={{ display: 'none' }} >;
}
}
// get whether this modal is visible by checking the state from the reducer against the modal id
const mapStateToProps = state => ({
isVisible: state.visibleModal === modalId
});
// for convenience we can add a closeModal prop to all modals
const mapDispatchToProps = dispatch => ({
closeModal: () => dispatch(ActionCreators.CloseModal());
});
return connect(mapStateToProps, mapDispatchToProps)(WrapperComponent);
}
}
然后在你的实际模式中:
// MyModal.jsx
import React from 'react';
import ModalDecorator from './ModalDecorator.jsx';
class MyModal extends React.Component {
render () { /* Do your thing here */ }
}
export default ModalDecorator('my-modal-id')(MyModal);
这里需要注意的是,所有模态都必须在某处呈现,因此请为它们制作一个基本容器:
// ModalDeclarations.jsx
import MyModal from './MyModal.jsx';
import SomeOtherModal from './SomeOtherModaal.jsx';
const ModalDeclarations = () => (
<div>
<MyModal/>
<SomeOtherModal/>
</div>
);
export default ModalDeclarations;
并在 App.jsx
import React from 'react'
import ModalDeclarations from './ModalDeclarations.jsx';
export default class App extends React.Component {
render () {
return (
<div>
{/* Other bits of your app here */}
<ModalDeclarations />
</div>
);
}
}
最后,我们可以在任何地方使用 OpenModal 动作创建器来打开任何模式。这是一个按钮,它将使用它的道具中的 modalId 打开模式。
// ModalButton.jsx
import React from 'react';
import {connect} from 'react-redux';
import {ActionCreators} from './modal-action-reducer.js';
const mapDispatchToProps = (dispatch, ownProps) => ({
openModal: () => dispatch(ActionCreators.OpenModal(ownProps.modalId))
});
class ModalButton extends React.Component {
render () {
return (
<div onClick={this.props.openModal} >
{this.props.children}
</div>
)
}
}
export default connect(null, mapDispatchToProps)(ModalButton);
ModalButton.propTypes = {
modalId: React.PropTypes.string.isRequired
};