[英]How to pass Props() value into setState() to make modal form editable using ReactJs
我正在創建我的blog
, user
可以在其中edit
他/她的博客。 在這里,我將數據彈出到模態中以進行此edit
..
所以在調試和更好的思考之后我已經弄清楚了。 這是我更新的modal
工作代碼
感謝您的時間。
//博客.js
class Blogs extends Component{
constructor(props) {
super(props);
this.state = {
modal: false,
justClicked: null,
activePage: 1,
requiredItem : null,
_id: '',
blog_short_desc:'',
blog_name: '',
blog_desc: '',
blog_image_link: '',
blog_by: '',
blog_by_author: ''
};
this.handleOpenDialog = this.handleOpenDialog.bind(this);
this.handleCloseDialog = this.handleCloseDialog.bind(this);
this.replaceModalItem = this.replaceModalItem.bind(this);
this.onTodoChange = this.onTodoChange.bind(this);
}
static propTypes = {
getBlog: PropTypes.func.isRequired,
deleteBlog: PropTypes.func.isRequired,
updateBlog: PropTypes.func.isRequired,
resume: PropTypes.object.isRequired,
auth: PropTypes.object.isRequired,
loading: PropTypes.object.isRequired
}
toggle = (id) => {
this.setState({
modal: !this.state.modal
});
}
componentDidMount() {
this.props.getBlog();
}
replaceModalItem(id, blog_short_desc, blog_name , blog_desc, blog_image_link, blog_by, blog_by_author) {
this.setState({
modal: true,
requiredItem: id,
_id: id,
blog_short_desc: blog_short_desc,
blog_name: blog_name,
blog_desc: blog_desc,
blog_image_link: blog_image_link,
blog_by: blog_by,
blog_by_author: blog_by_author
});
}
onTodoChange = (e) => {
this.setState({
[e.target.name] : e.target.value
});
}
onSubmit = (e, id) => {
e.preventDefault();
const updatedBlog = {
blog_short_desc: this.state.blog_short_desc,
blog_name: this.state.blog_name,
blog_desc: this.state.blog_desc,
blog_image_link: this.state.blog_image_link,
blog_by: this.props.auth["user"]._id,
blog_by_author: this.props.auth["user"].name
}
//update blog via updateblog action
this.props.updateBlog(id, updatedBlog);
alert("Blog updated successfully!");
e.target.reset();
this.toggle();
window.location.reload();
}
handleOpenDialog(id) {
this.setState({
openDialog: true,
OpenEditDialog: true,
justClicked: id
});
}
handleCloseDialog() {
this.setState({
openDialog: false
});
}
onDeleteBlogClick = (id) => {
this.props.deleteBlog(id);
};
handlePageChange(pageNumber) {
this.setState({activePage: pageNumber});
}
render(){
const { blogs, loading} = this.props.resume;
const { user, isAuthenticated } = this.props.auth;
const itemsPerPage = 6;
let activeBlogs = blogs.slice (itemsPerPage * this.state.activePage - itemsPerPage, itemsPerPage * this.state.activePage);
return(
<Container>
{loading ? (
<div><Loading/></div>
) : (
<div>
{/* blog modal */}
<BlogModal />
{/* card dialog */}
<BlogData blogs={blogs} user={this.props.auth} handleCloseDialog={this.handleCloseDialog} {...this.state} toggle={this.toggle}/>
{/* edit card dialog */}
<EditBlog onTodoChange={this.onTodoChange} {...this.state} toggle={this.toggle} onSubmit={this.onSubmit}/>
<Grid style={{padding: 0}} className="blog-grid">
{activeBlogs.map((item, i) => (
<Cell key={item._id} data-id={item._id} className="blog-grid-cell">
<Card shadow={5} className="cards-grid">
{item.blog_image_link ?
(<CardTitle style={{color: '#fff', height: '200px',
width: 'auto', backgroundImage: `url(${item.blog_image_link})`, backgroundPosition: 'center',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat'}}></CardTitle>) :
(<CardTitle className="card-title-image"></CardTitle>
)
}
<CardText>
<b>{item.blog_short_desc}</b>
</CardText>
<CardActions border>
<p className="block-data-details">
<Button className="blog-read-me-button col-4" onClick={this.handleOpenDialog.bind(this, item._id)}>Read </Button>
{ isAuthenticated === true && (item.blog_by === user._id) ?
<span className="col=8">
<Button className="remove-btn-blog-post"
color="danger"
size="sm"
onClick= {this.onDeleteBlogClick.bind(this, item._id)} title="Delete Blog">
×
</Button>
<a className="btn edit-btn-blog-post" href="#"
onClick={this.replaceModalItem.bind(this, item._id, item.blog_short_desc, item.blog_name, item.blog_desc, item.blog_image_link, item.blog_by, item.blog_by_author )} title="Edit Blog">
<i className="fa fa-pencil" aria-hidden="true"></i>
</a>
</span> : null }
</p>
<p style={{ fontWeight:'bold'}}>By-{item.blog_by_author} <span style={{float:'right',}}>{Moment(item.date).format('Do MMMM YYYY')}</span></p>
</CardActions>
</Card>
</Cell>
))}
</Grid>
</div>
)}
<Pagination
activePage={this.state.activePage}
itemsCountPerPage={6}
totalItemsCount={blogs.length}
pageRangeDisplayed={5}
onChange={this.handlePageChange.bind(this)}
itemClass='page-item'
linkClass='page-link'
/>
</Container>
)
}
}
const mapStateToProps = (state) => ({
resume: state.resume,
auth: state.auth,
loading: state.apiCallsInProgress > 0
});
export default connect(mapStateToProps, {getBlog, deleteBlog, updateBlog }) (Blogs);
//編輯.js
const EditBlog = ({ toggle, onTodoChange, onSubmit, ...state}) => {
return(
<span>
<Modal
isOpen = {state.modal && state.requiredItem === state._id}
toggle = {()=>this.toggle(state._id)}
>
<ModalHeader toggle={toggle} style={{fontWeight: "bold"}}>
Edit your blog {state.blog_name}
</ModalHeader>
<ModalBody>
<Form onSubmit={e => onSubmit(e, state._id )}>
<FormGroup>
<Label for="blogHeading">Blog Heading</Label>
<Input type="text" name="blog_short_desc" id="blogHeading" placeholder="Update one liner"
onChange={onTodoChange} defaultValue={state.blog_short_desc}/>
<Label for="blogName">Blog Name</Label>
<Input type="text" name="blog_name" id="blogName" placeholder="Update blog name"
onChange={onTodoChange} defaultValue={state.blog_name}/>
<Label for="desc1">Description </Label>
<Input type="textarea" name="blog_desc" id="desc1" placeholder="Update your blog"
onChange={onTodoChange} defaultValue={state.blog_desc}/>
<Label for="imageUrl">Image Url</Label>
<Input type="text" name="blog_image_link" id="imageUrl" placeholder="Update image url (Optional)"
onChange={onTodoChange} defaultValue={state.blog_image_link}/>
<Button
color="dark"
style={{marginTop: '2rem'}}
block
>Edit blog</Button>
</FormGroup>
</Form>
</ModalBody>
</Modal>
</span>
)
}
const mapStateToProps = state => ({
resume: state.resume,
auth: state.auth
})
export default connect(mapStateToProps, { updateBlog })(EditBlog);
//工作edit
的當前UI
首先,不可編輯的錯誤是由於在“defaultValue”內的模態中使用“value”道具輸入造成的。 如果你使用價值,你總是給它初始道具的價值。 使用默認值。 使用 defaultValue 使其成為受控組件。 在此處閱讀有關 Stackoverflow 的更多信息。 更改它並查看下一個問題(如果有)。
其次,確保避免使用 UNSAFE_componentWillReceiveProps() 。 查看您的 componentWillRecieveProps 方法,文檔中所說的可能在起作用:
“調用 this.setState() 通常不會觸發 UNSAFE_componentWillReceiveProps()。”
更新:
刪除 componentWillReceiveProps 方法。 提交應該工作。 並確保用戶已通過身份驗證。
在我看來,您的onTodoChange
function 正在父Blogs
組件上設置 state,但 state 不會返回輸入值。 相反,父級將blogs
屬性傳遞給EditBlogs
,並且由於onTodoChange
從不影響blogs
,因此輸入的value
保持不變。
這意味着您輸入的onChange
事件值 ( e.target.value
) 永遠不會返回輸入的value
屬性,因此輸入實際上不會更改值。
由於state
和onTodoChange
中的blog_
值都是編輯表單的本地值,我建議將它們向下移動到那個級別。 Blogs
不需要知道這些東西,它會簡化事情 - onTodoChange
會將事件值設置為state
,它將作為值流回輸入。
你的blogs
道具應該只設置初始的state
。
當一個用戶在編輯他們的博客時,拿他們的博客信息並創建一個 object 像這樣
userBlogData={
blog_heading: 'users blog heading',
blog_name: 'users blog name',
description: 'users blog description',
image_url: 'users blog image url',
}
根據這些對象更新模態形式。 例如:
<input name="blog_heading" value={blog_heading} ... />
用戶編輯完 object 后,您可以在您的服務器上發出更新請求,同時調用 get function 來更新博客。 您可以在編輯組件上保留更新 function。 但是 get function 將作為道具傳遞。
希望這可以幫助
這應該給你的想法......................................
// Edit Component
this.state = {
blog_name:this.props.data.blog_name
}
onBlogUpdate = () => {
let payload = this.state
API CALL...
}
...
render(){
return(
<input value={this.state.blog_name} name='blog_name' onChange={...} ... />
)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.