【问题标题】:unable to stop rendering component in Reactjs无法停止在 Reactjs 中渲染组件
【发布时间】:2018-07-09 07:55:38
【问题描述】:

在我的 reactjs 应用程序中,我正在使用 ReduxRedux-Thunk。在使用 google-maps 的组件中,我想使用标记实现 center_changed。所以每当我移动标记 latlngaddress 也会改变。当我保存状态组件时会刷新。所以我想停止使用shouldComponentUpdate 渲染我的组件。但是当我从shouldComponentUpdate 返回false 时,地图也会刷新。
我的组件

class StepTwo extends React.Component{
    constructor(props){
        super(props);
        this.state={
            pickupConfirmButton:false,
            dropoffConfirmButton:false,
        }
        this.mapLoaded = false;
        this.map=false;
        this.pickMarker=false;
        this.pickIcon = '';
        this.dropMarker=false;
        this.dropIcon='';
    }
    componentWillReceiveProps(props){
        if (props.isScriptLoadSucceed) {
            this.mapLoaded= true;
            this.directionsService = new google.maps.DirectionsService();
            this.directionsDisplay = new google.maps.DirectionsRenderer({ suppressMarkers: true });

            this.map = new google.maps.Map(document.getElementById('map'), {
                zoom: 14,
                center: { lat: 17.3850, lng: 78.4867 },
                mapTypeControl: false,
                streetViewControl: false,
                gestureHandling:'greedy',
            });

            this.pickMarker = new google.maps.Marker   ({
                icon:this.pickIcon,
                map: this.map,
                animation: google.maps.Animation.DROP,
                position: { lat: 17.3850, lng: 78.4867 },
                // draggable: true
            });
            this.dropIcon = {
                path: 'M 0,0 C -2,-20 -10,-22 -10,-30 A 10,10 0 1,1 10,-30 C 10,-22 2,-20 0,0 z M -2,-30 a 2,2 0 1,1 4,0 2,2 0 1,1 -4,0',
                fillColor: '#00E64D',
                fillOpacity: 1,
                strokeColor: '#000',
                strokeWeight: 1,
                scale: 1,
            };

            this.pickMarker.addListener('click', () =>{
                this.pickupMarkerClickListener();
            });
        }
    }
    shouldComponentUpdate(nextProps, nextState) {
        if (this.props.pickupAddress || nextProps.pickupAddress) {
           //after return false also i'm unable to stop rendering 
           //component
            return false;
        }
    }

    pickupMarkerClickListener = () =>{
        if(this.dropMarker){
            this.dropMarker.setVisible(false);
        }
        this.directionsDisplay.set('directions', null);
        this.map.setCenter(this.pickMarker.getPosition());
        this.map.setZoom(18);

        this.map.addListener('center_changed',  () => {
            let lat=this.map.getCenter().lat();
            let lng=this.map.getCenter().lng();
            let pickLatlng ={lat:lat,lng:lng};
            //on below function when i want to send latlng to redux state component getting refresh.
            // this.props.pickupHandler(pickLatlng);
            let geocoder = new google.maps.Geocoder;
                geocoder.geocode({'location': {lat:lat,lng:lng}}, (results, status) =>{
                    if (status === 'OK') {
                        ////////////////////////////////////////////////////////
                        //////// this is function which getting refresh/////////
                        ///////////////////////////////////////////////////////
                        this.props.pickupAddHandler(results[0].formatted_address);
                    }
                })
            this.pickMarker.setPosition({lat:lat,lng:lng});
        })
    }
    render(){
        return(
            <Row type="flex" justify="space-around" align="middle" className='stepTwo'>
                <Col lg={{span:10}} className="form" >
                    <Input 
                            className='input'
                            placeholder='Enter Pick-up Locaiton'
                            id='pick'
                            ref="pickupInput"
                            onChange={this.pickupSearch}
                            // value={this.props.pickupAddress}
                        />
                    <div style={{padding:'1rem'}} align='center'>
                    <Button><Icon type="swap"  className="swapIcon" /> </Button><span style={{fontSize:'0.8rem'}}>*Reverse Location</span>
                    </div>
                    <Input 
                        className='input'
                        placeholder='Enter Drop-off Locaiton'
                        ref="dropoffInput"
                        onChange={this.dropoffSearch}

                    />
                </Col>
                <Col lg={{span:13}}>
                    <div id="map"  className='map'></div>
                    {this.state.pickupConfirmButton && <Button  className="cnfrmBtn"  size="large" onClick={this.pickupMaker}>Confirm Location</Button> }
                    {this.state.dropoffConfirmButton && <Button className="cnfrmBtn" size="large" onClick={this.dropoffMaker}>Confirm Location</Button> }
                </Col>
            </Row>
        )
    }
}

const StepTwoLoadedMap = scriptLoader(
    [config.MapApi]
)(StepTwo);

const mapStateToProps = (state) =>{
    console.log(state.StepTwoReducer.pickupLatlng,'mapState')
    return{
        pickupAddress:state.StepTwoReducer.pickupAddress,
        pickupLocation:state.StepTwoReducer.pickupLatlng
    }
}
export default connect(mapStateToProps,{validationS2,pickupAddHandler,pickupHandler,dropoffHandler})(StepTwoLoadedMap);

ActionCreator

export function pickupAddHandler(address){
    return function(dispatch){
        dispatch({type:PICKUPADD,payload:address})
    }
}

export function pickupHandler(latlng) {

    return function(dispatch) {
        dispatch({ type: PICKUP_LATLNG,payload:latlng });
    };
}

Reducer.js

import {VALIDS2,PICKUPADD,PICKUP_LATLNG} from '../actions/types';
const INITIAL_STATE = {
    validStepTwo:false,
    pickupAddress:null,
    pickupLatlng:false,
};
export default  (state=INITIAL_STATE,action) => {
    // console.log(action,'step two')
    switch(action.type) {
        case PICKUPADD: 
            return {...state,pickupAddress:action.payload}
        case PICKUP_LATLNG:
            return {...state,pickupLatlng:action.payload}
        case VALIDS2:
            return {...state,validStepTwo:action.payload};
        default:
            return state;
    }
}

center_changed 时如何在 redux 状态下存储地址和 latlng,而无需渲染组件。
另一个问题是,当我更改地图的中心时,我将获得地址,如果我们停止渲染组件,我将存储 pickupAddress 状态的地址,有输入字段,所以我想将该地址显示为输入字段值,如果组件没有重新渲染然后我如何在输入字段中显示当前地址。
我不想使用任何库的一些原因
任何人都可以请帮助我如何存储 redux没有渲染的状态,但它应该在输入字段或任何其他简单方法中显示更新的值,我从 1 周开始就卡住了!plzzzzzz

【问题讨论】:

  • 如果我在componentWillReceiveProps 中运行地图,是否有任何prblm..?

标签: javascript reactjs redux react-redux redux-thunk


【解决方案1】:

总是尝试为第三方库(在这种情况下是谷歌地图)创建容器组件,并且 总是 在 shouldComponentUpdate 生命周期方法中返回 false。 提供其使用上下文的示例代码。

// GoogleMapComponent.jsx
import React, { Component } from 'react'

export default class GoogleMap extends Component {
    shouldComponentUpdate() {
        return false;
    }
    componentDidMount() {
        this.map = new google.maps.Map( this.refs.map, {
            center: {lat: this.props.lat, lng: this.props.lng},
            zoom: 5
        })
    }
    componentWillReceiveProps(nextProps) {
        this.map.panTo({ lat: nextPros.lat, lng: nextPros.lng });
    }
    render() {
        return (
            <div id="googleMap" ref="map" />
        )
    }
}


// App.jsx
import GoogleMap from './GoogleMapComponent'
import React, { Component } from 'react'

export default class App extends Component {
    constructor(props) {
        super(props);
        this.state = {lat: 30.397, lng: 130.876};
    }
    render() {
        return (
            <div style={{ height: '100%'}} >
                <button onClick={() => this.seState({ lat:50.712, lng: -30.08 }) }>
                    Your Favourite Place
                </button>
                <GoogleMap
                    lat={this.state.lat}
                    lng={this.state.lng}
                />
            </div>
        )
    }
}

这可能不是您问题的完美答案,但肯定会改善代码结构并帮助解决问题。 希望有帮助!!

【讨论】:

  • 我改变了我的项目结构,然后我的地图组件也重新渲染了
猜你喜欢
  • 2018-07-20
  • 1970-01-01
  • 1970-01-01
  • 2021-04-20
  • 2016-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-07
相关资源
最近更新 更多