#reactjs
#reactjs
Вопрос:
Мой app.js по сути, создает макет виджета. Она содержит функцию add, которая предназначена для извлечения selectedWidgetId из состояния и поиска его в массиве опций. У меня есть функция handleWidgetSelection, которая обновляет состояние selectedWidgetId на основе выбора во внешнем компоненте. Например, если пользователь выбирает «List», selectedWidgetId будет обновлен до «List». Что я замечаю, так это то, что состояние обновляется в handleWidgetSelection, но когда я использую его в функции добавления и регистрирую консоль, оно отображается как исходное состояние null и не может найти его в массиве widgetOptions. Любая помощь была бы отличной.
class App extends Component {
constructor(props) {
super(props);
this.state={
selectedWidgetId: null,
widgetOptions:[{name:"Data Table", comp:<DataTable/>},{name:"List", comp:<CheckboxList/>}],
widgets:[ //array for layout
{id:1, content: <DataTable/>},
{id:2, content: <CheckboxList/>},
{id:3, content: ""},
{id:4, content: ""}
],
isModalOpen: false
}
}
handleWidgetSelection=(id) => {
this.setState({ selectedWidgetId: id }, () => {
console.log('updated state value', this.state.selectedWidgetId) //this shows up correctly
})
}
addEvent=(index)=>{
this.setState({
isModalOpen: true
})
const copyWidgets=Object.assign([],this.state.widgets);
let widget = Object.assign({}, this.state.widgets[index]);
console.log(this.state.selectedWidgetId); //this shows up as null
widget.content=this.state.widgetOptions.find(w => w.name === this.state.selectedWidgetId).comp;//it is unable to find it in the array because it appears as the original state of null
copyWidgets[index]=widget;
this.setState({
widgets:copyWidgets
})
}
....
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<AddWidgetDialog handleWidgetSelection={this.handleWidgetSelection} widgets={this.state.widgetOptions} isModalOpen={this.state.isModalOpen} onRequestClose={this.onRequestClose} />
<Grid container spacing={24}>
{
this.state.widgets.map((widget,index)=>{
return(
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}><Swappable id={widget.id} content={widget.content} delete={this.deleteEvent.bind(this,index)} add={this.addEvent.bind(this,index)}/></Paper>
</Grid>
)
})
}
</Grid>
</div>
);
}
Заменяемый компонент:
import React, { Component } from 'react'
class Swappable extends Component {
constructor() {
super()
this.state = {
customFunc: null
}
}
allowDrop(ev) {
ev.preventDefault();
}
drag(ev, customFunc = null) {
ev.dataTransfer.setData("src", ev.target.id);
console.log(ev.target.parentNode, 'TARGET DRAGSTART')
this.setState({
initialParentNode: ev.target.parentNode
})
}
dragEnd(ev, customFunc = null) {
console.log(ev.target.parentNode, 'TARGET DRAGEND')
if (customFunc amp;amp; (ev.target.parentNode != this.state.initialParentNode)) {
console.log('custom func')
this.props.customFunc()
}
}
drop(ev, dragableId, dropzoneId, customFunc = null, swappable = true) {
ev.preventDefault();
let src = document.getElementById(ev.dataTransfer.getData("src"));
let srcParent = src.parentNode;
let target = document.getElementById(dragableId);
console.log(src, 'dragged element');
console.log(srcParent, 'parent of dragged');
console.log(target, 'element to be swapped')
swappable ? this.swapElements(src, target, srcParent) : this.transferElement(src, dropzoneId)
}
swapElements(src, target, srcParent) {
target.replaceWith(src);
srcParent.appendChild(target);
}
transferElement(src, dropzoneId) {
let dropzone = document.getElementById(dropzoneId)
dropzone.appendChild(src);
}
render() {
const dropZoneStyle = {
width: '450px',
minHeight: '300px',
padding: '10px',
border: '1px solid #aaaaaa'
};
const draggableStyle = {
width: '400px',
height: '300px',
padding: '10px',
border: '1px solid red'
};
const { id, content, swappable, customFunc } = this.props
const dropzoneId = 'drop' id
const dragableId = 'drag' id
console.log(customFunc, 'customFunc')
return (
<div
id = {dropzoneId}
onDrop={(event) => this.drop(event, dragableId, dropzoneId, customFunc, swappable)}
onDragOver={(event) => this.allowDrop(event)}
style={dropZoneStyle}>
<div id={ dragableId }
draggable="true"
onDragStart={(event) => this.drag(event)}
onDragEnd = {(event) => this.dragEnd(event, customFunc)}
style={draggableStyle}>
{ content }
<div>{content==""?<button onClick={this.props.add}>Add Widget</button>:<button onClick={this.props.delete}>Delete</button>}</div>
</div>
</div>
)
}
}
export default Swappable;
Компонент AddWidgetDialog:
import React, { PropTypes } from 'react';
import Modal from 'react-modal';
const AddWidgetDialog = ({ handleWidgetSelection, widgets, isModalOpen, onRequestClose}) => {
const widgetItems = widgets.map((widget) => {
return (
<div className="list-group">
<a href="#" onClick={() => handleWidgetSelection(widget.name)} className="list-group-item">
<h6 className="list-group-item-heading">{widget.name}</h6>
</a>
</div>
);
});
return (
<Modal
className="Modal__Bootstrap modal-dialog"
isOpen={isModalOpen}>
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" onClick={onRequestClose}>
<span aria-hidden="true">amp;times;</span>
<span className="sr-only">Close</span>
</button>
<h4 className="modal-title">Add a widget</h4>
</div>
<div className="modal-body">
<h5>Pick a widget to add</h5>
{widgetItems}
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" onClick={onRequestClose}>Close</button>
</div>
</div>
</Modal>
);
};
export default AddWidgetDialog;
Комментарии:
1. Когда вы выполняете функцию addEvent из
Swappable
компонента2. В функции возврата для нее после отображения содержимого я добавил компонент swappable и AddWidgetDialog в моем вопросе в качестве обновления для вашего комментария.
Ответ №1:
попробуйте заменить это add={this.addEvent.bind(this,index)}
просто функцией arrow:
add={()=> this.addEvent(index)}