我正在尝试发送动作以显示模态。
我得到的错误无法读取null的道具。
<div className="cell">
<button onClick={this.openAchievementModal} className="modal-button">+ Add Achievement</button>
</div>
点击处理程序:
openAchievementModal(){
this.props.showModal({
type: 'SHOW_MODAL',
modalType: 'DELETE_POST',
modalProps: {
postId: 42
}
})
}
我是如何用道具发送行动的?
更新:我有2个减速器,一个用于管理我的数据:
import {ADD_ACHIEVEMENT, ADD_ENJOYMENT } from '../constants/ActionTypes'
const initialState = [
{
date: "Fri 1st",
enjoyments: [],
achievements: [],
id: 0
},
{
date: "Sat 2nd",
enjoyments: ['Football', 'Rugby'],
achievements: ['Tennis', 'Football'],
id: 1
},
{
date: "Sun 3rd",
enjoyments: [],
achievements: [],
id: 2
},
{
date: "Mon 4th",
enjoyments: [],
achievements: [],
id:3
},
{
date: "Tue 5th",
enjoyments: [],
achievements: [],
id: 4
},
"isOpen": false
]
export default function days(state = initialState, action) {
switch (action.type) {
case ADD_ACHIEVEMENT:
return state.map(item => {
if (item.id === action.id) {
return Object.assign({}, item, {
achievements: [
...item.achievements,
action.text,
]
});
}
return item;
});
case ADD_ENJOYMENT:
return state.map(item => {
if (item.id === action.id) {
return Object.assign({}, item, {
enjoyments: [
...item.enjoyments,
action.text,
]
});
}
return item;
});
default:
return state
}
}
另一个管理我的模态:
import {SHOW_MODAL, HIDE_MODAL } from '../constants/ActionTypes'
import React from 'react';
import {connect} from 'react-redux';
import * as actions from '../actions';
import AddAchievementModal from '../components/modals/AddAchievementModal.js';
import RemoveAchievementModal from '../components/modals/RemoveAchievementModal.js';
const initialState = {
modalType: null,
modalProps: {}
}
function modal(state = initialState, action) {
switch (action.type) {
case 'SHOW_MODAL':
return {
modalType: action.modalType,
modalProps: action.modalProps
}
case 'HIDE_MODAL':
return initialState
default:
return state
}
}
在我的容器组件中,我有以下代码:
import React, { Component } from 'react'
import {connect} from 'react-redux'
import * as actions from '../actions'
class Achievement extends Component {
openAchievementModal(){
this.props.showModal({
type: 'SHOW_MODAL',
modalType: 'DELETE_POST',
modalProps: {
postId: 42
}
})
}
render() {
var options = [
{ value: 1, label: 'Play Music' },
{ value: 2, label: 'Football' }
];
let listItems
if(this.props.day.achievements) {
listItems = this.props.day.achievements.map((achievement) => (
<div className="cell" key={achievement + "_achievements"}>
{achievement}
<button onClick={this.openRemoveModal} className="modal-button">+ remove Achievement</button>
</div>
))
}
return (
<span key={this.props.day + "span"}>
{listItems}
<div className="cell">
<button onClick={this.openAchievementModal} className="modal-button">+ Add Achievement</button>
</div>
</span>
)
}
}
function mapStateToProps(state, ownProps) {
return {
days: state.days
};
}
export default connect(mapStateToProps)(Achievement);
我的ModelRoot组件:
import AddAchievementModal from '../components/modals/AddAchievementModal.js';
import RemoveAchievementModal from '../components/modals/RemoveAchievementModal.js';
const MODAL_COMPONENTS = {
'REMOVE_ACHIEVEMENT': RemoveAchievementModal,
'ADD_ACHIEVEMENT': AddAchievementModal,
/* other modals */
}
const ModalRoot = ({ modalType, modalProps }) => {
if (!modalType) {
return <span /> // after React v15 you can return null here
}
const SpecificModal = MODAL_COMPONENTS[modalType]
return <SpecificModal {...modalProps} />
}
export default connect(
state => state.modal
)(ModalRoot)
答案 0 :(得分:1)
openAchievementModal
未绑定到组件实例,因为JavaScript方法默认情况下不绑定类方法。请在构造函数中手动绑定它:
constructor() {
super()
this.openAchievementModal = this.openAchievementModal.bind(this)
}
或者在渲染功能中:
<button onClick={this.openAchievementModal.bind(this)} ... />
您也可以使用箭头函数语法来保留词汇(如bzekiunat所示):
<button onClick={() => { this.openAchievementModal() } } ... />
或者,如果您已经转换了代码,请使用class properties和箭头功能(注意= () =>
代替()
):
openAchievementModal = () => {
this.props.showModal({
type: 'SHOW_MODAL',
modalType: 'DELETE_POST',
modalProps: {
postId: 42
}
})
}
最终代码:
class Achievement extends Component {
constructor() {
super()
this.openAchievementModal = this.openAchievementModal.bind(this)
}
render() {
...
<button onClick={this.openAchievementModal} className="modal-button">+ Add Achievement</button>
...
}
}
请参阅以下示例了解不同的绑定方法:
class ConstructorBoundExample extends React.Component {
constructor() {
super()
this.openAchievementModal = this.openAchievementModal.bind(this)
}
openAchievementModal() {
console.log(this.props)
this.props.openModal("test")
}
render() {
return (
<button onClick={this.openAchievementModal} className="modal-button">Constructor bound - works</button>
)
}
}
class InlineBoundExample extends React.Component {
openAchievementModal() {
console.log(this.props)
this.props.openModal("test")
}
render() {
return (
<button onClick={this.openAchievementModal.bind(this)} className="modal-button">Inline bound - works</button>
)
}
}
class FunctionBoundExample extends React.Component {
openAchievementModal() {
console.log(this.props)
this.props.openModal("test")
}
render() {
return (
<button onClick={function() { console.log(this.props); this.openAchievementModal() }} className="modal-button">Function bound - does not work - and should not</button>
)
}
}
class ArrowBoundExample extends React.Component {
openAchievementModal() {
console.log(this.props)
this.props.openModal("test")
}
render() {
return (
<button onClick={() => { console.log(this.props); this.openAchievementModal() }} className="modal-button">Arrow bound - works</button>
)
}
}
class ES7ClassPropertyBoundExample extends React.Component {
openAchievementModal = () => {
console.log(this.props)
this.props.openModal("test")
}
render() {
return (
<button onClick={() => { console.log(this.props); this.openAchievementModal() }} className="modal-button">ES7 class property bound - works</button>
)
}
}
const openModal = message => {
alert(message)
}
class Examples extends React.Component {
render() {
return (
<div>
<ConstructorBoundExample openModal={openModal} />
<InlineBoundExample openModal={openModal} />
<FunctionBoundExample openModal={openModal} />
<ArrowBoundExample openModal={openModal} />
<ES7ClassPropertyBoundExample openModal={openModal} />
</div>
)
}
}
ReactDOM.render(<Examples />, document.getElementById('app'));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
&#13;
答案 1 :(得分:1)
如果您因某些原因不想使用bind
,可以包装this.openAchievementModal
功能。
<div className="cell">
<button onClick={() => this.openAchievementModal()} className="modal-button">+ Add Achievement</button>
</div>
答案 2 :(得分:0)
我没有在任何地方看到showModal
。据我了解,showModal
必须发出一个动作。因此,您必须将第二个参数传递给connect
函数:mapDispatchToProps
function mapDispatchToProps(dispatch) {
return {
showModal() {
dispatch(
type: 'SHOW_MODAL',
modalType: 'DELETE_POST',
modalProps: {
postId: 42
}
)
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Achievement)
之后,您只需在函数this.props.showModal()
openAchievementModal
即可
编辑:我看到postId
是硬编码的,您可能要考虑将值作为函数showModal
的参数传递