簡體   English   中英

通過子組件更改父狀態時,React重新渲染

[英]React Re-renders When Parent State is Changed Through Child Component

在App.js中,我將setURL(page){ ... }作為對HealthForm的支持。 在HealthForm中,我有一個輸入字段,該字段接受URL的String和一個按鈕,該按鈕發起對后端服務器的提取調用,並且一些數據會在promise對象中接收回來。 我也叫that.props.changeUrl(that.state.someURL); 在promiseStatus函數內部,因為那是我唯一可以放置它而不收到以下警告的地方:

Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

但是,每次調用that.props.changeUrl(that.state.someURL) ,頁面都會重新渲染。 基本上-輸入字段和由於fetch調用而呈現的其他功能-全部重置。 但是App.js中的url狀態會更新。

為什么在調用父項道具時整個頁面都重新渲染?

如果僅刪除了那行that.props.changeUrl(that.state.someURL)但該應用程序不會重新呈現,但是它當然不會更改該應用程序的狀態

我需要頁面不重新呈現,因為重要信息是在fetch調用之后呈現的,由於重新呈現會重置該路由,因此無法看到。

App.js

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            url: '',

        };
        this.setURL = this.setURL.bind(this);
    }

    setURL(link) {
        this.setState({
            url: link
        });
    }

    render(){
        return(

            <MuiThemeProvider>
                <Router>
                    <div className="App">
                        <Route path="/" component={Header}></Route>

                        <Route path="/health" component={()=>(
                            <HealthForm changeUrl={this.setURL}/>)}></Route>

                        <Route path="/path1" component={wForm}></Route>
                        <Route path="/path2" component={xForm}></Route>
                        <Route path="/path3" component={yForm}></Route>
                        <Route path="/path4" component={zForm}></Route>

                    </div>
                </Router>
            </MuiThemeProvider>
        );
    }   
}

HealthForm.js

class HealthForm extends React.Component {
  constructor(props) {
   super(props);
    this.state = {
        exampleURL: '',
        exampleURLError: '',
        status: '',
        showStatus: false
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
 }

 validate = () => {
 //…checks for input errors
       }

 handleChange(event) {
    this.setState({
        [event.target.name]: event.target.value
    });
 }

 handleSubmit(event) {
    event.preventDefault();
    const err = this.validate();
    let that = this;
    if (!err) {
                   this.setState({
        exampleURLError: ''
        });
        console.log(this.state);
        var data = this.state.exampleURL

        fetch('htpp://...', {
                    method: 'POST',
                    body: JSON.stringify(data)
                })
                .then((result) => {
                    var promiseStatus = result.text();
                    promiseStatus.then(function (value) {
                        that.setState({
                            status: value,
                            showStatus: true
                        });
                        that.props.changeUrl(that.state.jarvisURL);
                    });
                }).catch((error) => {
                    console.log(error);
                });
    }
 }

 render() {
        return (
            <form>  
            <TextField
              ...
            />
            <br/>

             <Button variant="contained" size="small" color="primary"     onClick={e => this.handleSubmit(e)} >
                Check
            </Button>
            <br />  <br /> 

             ...

            </form>  
        );
 }
}
export default HealthForm;

之所以發生這種情況,是因為您在App組件上調用setState() ,導致其重新呈現,包括重新創建您設置的所有路由。 我不確定您使用的是哪個路由器,但是似乎它是在路由下重新創建組件,可能是通過再次調用作為道具傳入的component函數並獲取HealthForm組件的新實例。

我假設App中的所有組件都要求您將狀態存儲在App中,這就是為什么要將其放置在其中? 如果不是,請將其向下移到HealthForm組件中,但是如果是這樣,可能是時候考慮將狀態外部存儲到組件中了,例如,在諸如Redux之類的狀態容器中或其他具有Flux風格的東西中。

編輯:我認為您的問題的根源在這里:

<Route path="/health" component={()=>(<HealthForm changeUrl={this.setURL}/>)}></Route>

事實上,函數是作為component prop傳遞的,每次都會導致component的新實例。 我可以看到為什么需要這樣做,以將對setURL()的引用傳遞到HealthForm -通過從組件中提取狀態也可以避免這種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM