componentWillReceiveProps 多次渲染

Posted

技术标签:

【中文标题】componentWillReceiveProps 多次渲染【英文标题】:componentWillReceiveProps render multiple times 【发布时间】:2020-06-17 08:40:33 【问题描述】:

我正在使用三个不同的函数从我的数据库中获取数据,但正如我所见,在这种情况下 componentWillReceiveProps 会重新渲染三次,这会导致我在前端复制我的元素。我怎样才能只渲染一次,或者只有对象的道具真正改变。到现在为止,我的 follow[] 数组对象都在复制


class UserDashboard extends React.Component 

    state = 
        uid: this.props.userDetails.uid,
        page: 1,
        redirect: false,
        target: 15,
        selectedRole: 4,
        selectedSourceRole: 1,
        quote_nr: '',
        source_id: '',
        status_id: '',
        cost: '',
        rebate: '',
        pageLoading: false,
        date: '2222-01-02',
        therapists:[],
        globalTargets:[],
        follows:[],
        utc: new Date().toISOString().slice(0, 19).replace('T', ' '),
    

    topProfilesUrl = 'therapists/top/profiles';
    getGlobalTargets = 'owner/targets';
    followActivities = 'user/follow/activities';

    componentDidMount = () => 
        const  getActivities,getFollowActivities,getTarget  = this;
        getActivities();
        getFollowActivities();
        getTarget();
        window.scrollTo(0, 0);
    

    UNSAFE_componentWillReceiveProps = (newProps) => 

        let apiDat = newProps.apiDat;

        let apiData = newProps.apiData;
        if (apiData.activities && apiData.activities.success ) 
            let therapists = apiData.activities.therapists;
            let hasMore = true;
            console.log("unu")

            if (therapists.length < 10) 
                hasMore = false;
            

            this.setState(() => (
                therapists: this.state.therapists.concat(therapists),
                hasMore: hasMore,
                pageLoading: false
            ))
        
        if (apiDat.targets && apiDat.targets.success) 
            console.log("doi")

            let globalTargets = apiDat.targets.globals;
            let hasMore = true;
            if (globalTargets.length < 10) 
                hasMore = false;
            

            this.setState(() => (
                globalTargets: this.state.globalTargets.concat(globalTargets),
            ))
        
        if (apiData.followActivities && apiData.followActivities.success) 
            console.log("trei")

            let follows = apiData.followActivities.follows;
            let hasMore = true;
            if (follows.length < 10) 
                hasMore = false;
            

            this.setState(() => (
                follows: this.state.follows.concat(follows),
            ))
        
    
    getTarget = () => 
        this.setState(pageLoading: true, () =>  this.loadTargets() )
    

    loadTargets = () => 

        console.log("load")
        this.props.actions.reqGetGlobalTargets(
            body: ,
            headers: null,
            resource: `$this.getGlobalTargets?page=$this.state.page`
        )
    
    getFollowActivities= () => 
        this.setState(pageLoading: true, () =>  this.loadFollowActivities() )
    
    loadFollowActivities = () => 
        console.log("load")
        this.props.actions.reqGetFollowActivities(
            body: ,
            headers: null,
            resource: `$this.followActivities?page=$this.state.page`
        )
    
    renderLeads = () => 
        return (
            this.state.globalTargets.slice(0,1).map( (t, idx) => (
                t.daily_leads
            ))
        )
    
    renderSales = () => 
        return (
            this.state.globalTargets.slice(0,1).map( (t, idx) => (
                t.daily_sales
            ))
        )
    
    renderRatio = () => 
        return (
            this.state.globalTargets.slice(0,1).map( (t, idx) => (
                t.close_ratio
            ))
        )
    
    getActivities = () => 
        this.setState(pageLoading: true, () =>  this.loadActivities() )
    

    loadActivities = () => 
        this.props.actions.reqGetTherapistsTopProfiles(
            body: ,
            headers: null,
            resource: `$this.topProfilesUrl?page=$this.state.page`
        )
    

    renderActivities = () => 
        const items = this.state.therapists.map( (t, idx) => (
            <tr key=t.id className="activity-display-table">
                <td>Quote Nr.: t.quote_nr</td>
                <td>Source: t.source_id</td>
                <td>Status: t.status_id</td>
                <td>Cost: $t.cost</td>
                <td>Rebate: $t.rebate</td>
                <td>Date: t.date.slice(0,10).replace(/-/g,'-')</td>
            </tr>
        ))

        return (
            <div ref=0 className="therapist-list">
                <h2>Your Past Entries: </h2>
                 items 
            </div>
        )
    
    renderFollowActivities = () => 

        const items = this.state.follows.map( (t, idx) => (
            <tr key=t.id className="activity-display-table">
                <td>Quote Nr.: t.quote_nr</td>
                <td>Source: t.source_id</td>
                <td>Status: t.status_id</td>
                <td>Cost: $t.cost</td>
                <td>Rebate: $t.rebate</td>
                <td>Date: t.date.slice(0,10).replace(/-/g,'-')</td>
            </tr>
        ))

        return (
            <div ref=0 className="therapist-list">
                 items 
            </div>
        )
    
    submitUrl = 'registerActivities';

    handleChange = (eve) => 

        let inputName = eve.target.name,
            value = eve.target.value;

        this.setState(() => 
            return [inputName]: value
        )
    

    handleSubmit = () => 

        this.setState(() => 

            const acBody = 
                quote_nr: this.state.quote_nr,
                cost: this.state.cost,
                source_id: this.state.selectedSourceRole,
                status_id: this.state.selectedRole,
                date: this.state.utc,
                rebate: this.state.rebate,
                user_id:this.state.uid,
            
           this.props.actions.reqActionsUsers(acBody, this.submitUrl);
        )

    

    handleStatusChange = (event) => 
        let statusId = event.target.value;
        this.setState(() => (
            selectedRole: statusId
        ))
    

    handleSourceChange = (ev) => 
        let statusId = ev.target.value;
        this.setState(() => (
            selectedSourceRole: statusId
        ))
    

    render () 
        console.log(this.state.follows);

        return (
            <MainWrapper>
                <div id="user-dashboard">
                    <HeaderUser logoutRedirect="/signin"/>
                    <div className="page-background">
                        <SidebarUser page="dashboard"/>
                        /* Page Content */
                        <div className="inner-content">
                            <div className="top-row">
                                <h1>Salesperson Dashboard</h1>
                            </div>
                            <div className="second-row">
                            </div>
                            <div className="activity-table">
                                <table className="a">
                                    <tr>
                                        <th>Today's Targets (this.state.utc.slice(0,10).replace(/-/g,'-'))</th>
                                        <th>Weekly Targets</th>
                                        <th>Bonus So Far This Week</th>
                                    </tr>
                                    <tr>
                                        <td>0/this.renderLeads() Leads Handled</td>
                                        <td>0/this.renderLeads()*5 Leads Handled</td>
                                        <td>$0 From Leads</td>
                                    </tr>
                                    <tr>
                                        <td>0/this.renderSales() Sales</td>
                                        <td>0/this.renderSales()*5 Sales</td>
                                        <td>$0 From Sales</td>
                                    </tr>
                                    <tr>
                                        <td>0/this.renderRatio() Close Ratio</td>
                                        <td>0/this.renderRatio()*5 Close Ratio</td>
                                        <td>$0 From Profit Share</td>
                                    </tr>
                                </table>
                            </div>
                            <div>
                               <h2>Leads Due For A Followup</h2>
                                 this.renderFollowActivities() 

                            </div>
                            <h2 className="activity">Add Activity</h2>
                            <div className="activity-menu">
                                <input type="text"
                                       placeholder="Quote Number"
                                       name="quote_nr"
                                       onChange=this.handleChange
                                     />
                                    <select  onChange=this.handleSourceChange>
                                        <option value="1">Phone</option>
                                        <option value="2">Email</option>
                                        <option value="3">Live Chat</option>
                                    </select>
                                <select  onChange=this.handleStatusChange>
                                    <option value="4">Lead</option>
                                    <option value="5">Sold</option>
                                </select>
                                <input type="text"
                                       placeholder="Cost"
                                       name="cost"
                                       onChange=this.handleChange
                                />
                                <input type="text"
                                       placeholder=this.state.cost/20||("Recom. Rebate" + " $")
                                       name="recRebate"
                                       readOnly
                                />
                                <input type="text"
                                       placeholder=this.state.cost/10||("Max Possible Rebate" + " $")
                                       name="maxRebate"
                                       readOnly
                                />
                                <input type="text"
                                       placeholder="Final Rebate $"
                                       name="rebate"
                                       onChange=this.handleChange
                                />
                            </div>
                            <ButtonRoundGradient className="activity_button" text="Add Activity" onClick=this.handleSubmit/>
                             this.renderActivities() 

                        </div>
                    </div>
                </div>
            </MainWrapper>
        )
    


const mapStateToProps = state => (
    apiData: state.activities,
    apiDat: state.targets,
    userDetails: state.userDetails

)
function mapDispatchToProps(dispatch) 
    return 
        actions: 
            reqGetGlobalTargets: bindActionCreators(reqGetGlobalTargets, dispatch),
            reqGetFollowActivities: bindActionCreators(reqGetFollowActivities, dispatch),
            reqGetTherapistsTopProfiles: bindActionCreators(reqGetTherapistsTopProfiles, dispatch),
            reqFetchUserDetails: bindActionCreators(reqFetchUserDetails, dispatch),
            reqActionsUsers: bindActionCreators(reqActionsUsers, dispatch),
        
    ;


export default connect(mapStateToProps, mapDispatchToProps)(UserDashboard)

【问题讨论】:

这能回答你的问题吗? How to check what props changed in componentWillReceiveProps @Agney 这是我所做的正确的事情,它解决了问题。谢谢!!!! 【参考方案1】:

ComponentWillRecieveProps 会在每次您的 state 更改或您的 state 更改时被调用,因此如果您想停止复制,您应该这样做:

componentWillReceiveProps(nextProps, nextContext) 
        if (JSON.stringify(nextProps.someProps.items) !== JSON.stringift(this.state.items))
// do something
         

基本上你应该检查你的组件的 props 和 state 是否应该对这种情况做出反应,然后真正渲染你的应用程序。

希望对你有帮助

【讨论】:

以上是关于componentWillReceiveProps 多次渲染的主要内容,如果未能解决你的问题,请参考以下文章

为啥 React 保留 componentWillReceiveProps 和 shouldComponentUpdate 方法?

react componentWillReceiveProps

如何明确替换 componentWillReceiveProps 并不断获取 nextProps?

将项目中的componentWillReceiveProps切换到getDerivedStateFromProps

何时使用 componentWillReceiveProps 生命周期方法?

将对象作为道具传递是不是会干扰 componentWillReceiveProps?