如何将 Props() 值传递给 setState() 以使用 ReactJs 使模态形式可编辑

How to pass Props() value into setState() to make modal form editable using ReactJs

我正在创建我的 blog,其中 user 可以 edit his/her 博客。 在这里,我将数据弹出到一个模态中,使这个 edit..

所以在调试和更好的思考之后我已经弄明白了。这是我为 modal

更新的工作代码

感谢您的宝贵时间。

//blog.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">
                                                &times;
                                            </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);

//Edit.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);

//当前工作UIedit

在我看来,您的 onTodoChange 函数正在父 Blogs 组件上设置状态,但该状态不会返回到输入值。相反,父级将 blogs 属性传递给 EditBlogs,并且由于 onTodoChange 永远不会影响 blogs,输入的 value 保持不变。

这意味着您输入的 onChange 事件值 (e.target.value) 永远不会返回输入的 value 属性,因此输入实际上不会更改值。

由于 stateonTodoChange 中的 blog_ 值都是编辑表单的局部值,我建议将它们向下移动到该级别。 Blogs 不会不需要知道这些东西,它会简化事情 - onTodoChange 会将事件值设置为 state,它将作为值直接流回输入。

您的 blogs 道具应该只设置初始 state

当用户编辑他们的博客时,获取他们的博客信息并创建一个这样的对象

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} ... />

用户编辑完对象后,您可以在您的服务器上发出更新请求,同时调用get函数来更新博客。您可以在编辑组件上保留更新功能。但是 get 函数将作为 props 传递。

希望对您有所帮助

这应该会给你思路......................................

    // 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={...} ... />
        )
     }

首先,不可编辑的错误是由于在 "defaultValue" 的模态中使用 "value" 道具输入造成的。如果你使用价值,你总是给它初始道具的价值。使用默认值。使用 defaultValue 使其成为受控组件。在 Whosebug here 上阅读更多内容。更改它并查看下一个问题(如果有)。

其次,确保避免UNSAFE_componentWillReceiveProps()。查看您的 componentWillRecieveProps 方法,文档中所说的可能在起作用:

"Calling this.setState() generally doesn’t trigger UNSAFE_componentWillReceiveProps()."

更新:

删除 componentWillReceiveProps 方法。提交应该工作。并确保用户已通过身份验证。

我已经用

弄明白了
  1. OnClick of edit button 我传递了所有必需的数据。 因此,我的 replaceModalItem()setState()

  2. 中的所有数据绑定在一起
  3. replaceModalItem中我调用了那些数据并将其设置为setState()

  4. Edit.js中我调用了所有state值。

因此在输入字段中获取所有必需的值,将其设置为 defaultValue