如何在React.js中从另一个组件调用不同组件的ComponentDidMount()

时间:2018-11-20 19:19:47

标签: reactjs

Api.js

    import React from 'react';
    import './Api.scss';
    import ProfileCard from 'components/Card/ProfileCard.jsx';
    import Modal from 'react-awesome-modal';

    class Api extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                title : '',
                content: '',
                img: '',
                data: []

            }
        }

        OnFileChange = (event) => {
            this.setState({img: event.target.files[0]});
        }

        onTitleChange = (event) => {
            this.setState({title: event.target.value})
        }

        onContentChange = (event) => {
            this.setState({content: event.target.value})
        }

        resetForm = () => {
            document.getElementById('title').value = '';
            document.getElementById('content').value = '';
            document.getElementById('img').value = '';
        }

        openModal() {
            this.setState({
                visible : true
            });
        }

        closeModal() {
            this.setState({
                visible : false
            });
        } 


        componentDidMount() {
            fetch('http://127.0.0.1:8000/get_profile/')
            .then(response => response.json())
            .then(res => this.setState({ data: res }));  
        }


        SubmitProfile = (event) => {
            let formData = new FormData();
            formData.append('img',this.state.img);
            formData.append('title',this.state.title);
            formData.append('content',this.state.content);
            fetch('http://127.0.0.1:8000/post_profile/', {
                method: 'post',
                headers: {
                    Accept: 'application/json, text/plain, */*'
                },
                body:formData,
            })
            .then(response => response.json())
            .then(res => {
                if (res.code === 200){
                    this.componentDidMount()
                    this.resetForm()
                    this.closeModal()
                }
                console.log(res);
            })
        }


        elasticSearch = (event) => {
            fetch('http://127.0.0.1:8000/search/', {
                method: 'post',
                headers:{'Content-Type': 'application/json'},
                body: JSON.stringify({
                    q: event.target.value 
                })
        })
        .then(response => response.json())
        .then(res => {
            console.log(res)
            this.setState({ data: res })
        });  
        }





        render(){
            return (
                <div className="api-body">
                    <section>
                        <div className="tc pa2">
                            <input
                                type="button"
                                className="br2 center ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib"
                                value="Post"
                                onClick={() => this.openModal()} 
                            />
                            <input
                                className="db ma3 q center border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2"
                                type="text"
                                name="q"
                                id="q"
                                placeholder="search here .."
                                onChange = {this.elasticSearch}
                            />
                            </div>
                            <Modal 
                                visible={this.state.visible}
                                width="400"
                                height="300"
                                effect="fadeInDown"
                                onClickAway={() => this.closeModal()}
                            >
                            <div className="mv3 pa3">

                            <label className="db fw6 lh-copy f6" htmlFor="password">Title</label>
                            <input
                                className="db border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2"
                                type="text"
                                name="title"
                                id="title"
                                onChange={this.onTitleChange}
                            />
                        </div>
                        <div className="mv3 pa3 mt-1">
                            <label htmlFor="comment" className="f6 b db mb2">Contents </label>
                            <textarea 
                                id="content" 
                                name="content" 
                                className="db border-box hover-black w-100 measure ba b--black-20 pa2 br2 mb2" 
                                aria-describedby="content-desc"
                                onChange={this.onContentChange}>
                            </textarea>
                        </div>
                        <div className="mv3 pa3 mt-1">
                        <input
                            type="file"
                            multiple = {false}
                            id="img"
                            name="img"
                            ref={(input) => { this.inpuElement = input; }}
                            accept=".jpg,.jpeg,.png,.pdf,.doc"
                            onChange={this.OnFileChange}
                            />
                        <input
                            type="button"
                            className="br2 center ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib"
                            value="Submit"
                            onClick={this.SubmitProfile} 
                            />
                        </div>
                        </Modal>
                    </section>

                <ProfileCard data={this.state.data} />
                </div>
            )
        }
    }


    export default Api;

ProfileCard.js

    import React from 'react';


    class ProfileCard extends React.Component {
    constructor(props){
        super(props)
        this.state = {
        data : []
        }
    }

    deleteProfile = id => e => {
        fetch('http://127.0.0.1:8000/delete_profile/', {
        method: 'post',
        headers:{'Content-Type': 'application/json'},
        body: JSON.stringify({
            id: id
        })
        })
        .then(response => response.json())
        .then(res => {
            if (res.code === 200){
            this.componentDidMount()
            }
            console.log(res)
        })
    } 

    render(){
    return (
        <div>
        {
        this.props.data.map((user,i) => {
            return (
            <article className='mw5 tc bg-white dib br3 pa3 ma3 pa4-ns mv3 ba b--black-10 shadow-5 pc-scroll pointer' key={i}>
            <div className="tc">

            <img 
                src={"http://127.0.0.1:8000" + user.photo}
                className="br-100 h3 w3 dib" 
                alt="profile pic"
                onDoubleClick = {this.deleteProfile(user.id)}
            />
                <h1 className="f4">{user.title}</h1>
                <hr className="mw3 bb bw1 b--black-10" />
            </div>
            <p className="lh-copy measure center f6 black-70">
            {user.content}
            </p>
            </article>
            );
        })
        }
        </div>
    );
    }
    }


    export default ProfileCard;

在我的ProfileCard中有一个功能deleteProfile,如您所见,以及我的componentDidMount 在Api组件上。我想在deleteProfile执行后立即调用componentDidMount。

我找不到任何适当的方法来执行此操作。 如果我直接发送componentDidMount也将无法正常工作 因为我正在将res分配给州。

2 个答案:

答案 0 :(得分:2)

componentDidMount是生命周期挂钩。不应直接调用它。语义上正确的方法是提供一种可以在两个地方重用的方法:

componentDidMount() {
  this.fetchData();
}

fetchData() {
    return fetch('http://127.0.0.1:8000/get_profile/')
    .then(response => response.json())
    .then(res => this.setState({ data: res }));  
}


SubmitProfile = (event) => {
    ...
    .then(res => {
        if (res.code === 200){
            return this.fetchData()
    ...
}

这也有利于可测试性。 fetchData可以与组件生命周期分开进行测试。此外,方法应返回promise,所有promise应链接在一起。

这里的问题是关注点分离。 ProfileCard应该为dumb component,并将所有工作委托给父母。此方法属于父Api组件:

deleteProfile = id => {
    fetch('http://127.0.0.1:8000/delete_profile/', ...)
    ...
    .then(res => {
        if (res.code === 200){
            this.fetchData()
        }
    })
} 

应将其传递给子组件:

<ProfileCard onDelete={this.deleteProfile} />

并在子组件中用作道具:

<img 
    src={"http://127.0.0.1:8000" + user.photo}
    className="br-100 h3 w3 dib" 
    alt="profile pic"
    onDoubleClick={() => this.props.onDelete(user.id)}
/>

答案 1 :(得分:1)

Dim EmployeeID As Integer = DirectCast(cbxEmployee.SelectedValue, EmployeeListItem).EID 在注释中是正确的。您不需要-也不需要-直接调用@estus,但是您可以从所有者组件中调用函数。

首先,我们创建一个用于获取配置文件的新功能。仍然可以在componentDidMount中调用它。

componentDidMount

然后我们将此功能作为fetchProfile() { fetch('http://127.0.0.1:8000/get_profile/') .then(response => response.json()) .then(res => this.setState({ data: res })); } componentDidMount() { this.fetchProfile() } 传递到prop

<ProfileCard />

最后,我们在<ProfileCard data={ this.state.data } onProfileDelete={ () => this.fetchProfile() } /> 中删除了个人资料后,将其称为prop

ProfileCard