繁体   English   中英

如何在反应中获取调用后让父组件重新渲染?

[英]How to get parent component to re render after a fetch call in react?

我希望父组件在此获取请求完成时重新呈现。 使用当前的代码,它似乎在 fetch 完成之前渲染,无论如何。 我猜这是由于 fetch 的异步性质? 有没有办法在 .then() 中以某种方式实现? 试图在 .then() 中调用“this.props.rerenderParentCallback()”给我错误。

submit = (e) => {
        e.preventDefault();
        const myInit1 = {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*',
                'Vary': 'Origin'.replace,
                'Accept': 'application/json'
            },
            body: JSON.stringify({
                "username": this.state.username,
                "password": this.state.password,
                "email": this.state.email
            })
        };
        console.log(myInit1.body);
        let authurl = 'http://localhost:8080/authenticate';
        if(!!localStorage.getItem("token"))
        localStorage.removeItem("token");
        try {
            fetch(authurl, myInit1)
                .then((response) => {
                    return response.json();
                })
                .then(function (myJson) {
                    console.log(myJson.token);
                    localStorage.setItem("token", myJson.token);
                    console.log("isAuth " + !!localStorage.getItem("token"));    
                }).then();
                
        } catch (e) {

        }finally{
            this.props.rerenderParentCallback();
        }
        
    }

在 AJAX 操作完成之前,您正在立即调用该函数:

this.props.rerenderParentCallback();

AJAX 是异步的。 您希望响应异步操作而发生的任何事情都将在附加到操作的.then() (或在await ,或在传入的回调中,具体取决于异步操作的结构)。

在这种情况下,您还需要考虑到this在回调中意味着不同的事实。 为此,只需将函数引用分配给一个变量并引用该变量。 像这样的东西:

const callback = this.props.rerenderParentCallback;

// then, in your .then() callback:
.then(function (myJson) {
    console.log(myJson.token);
    localStorage.setItem("token", myJson.token);
    console.log("isAuth " + !!localStorage.getItem("token"));
    callback(); // <--- invoke the function
})

(您也可以完全摆脱 try/catch/finally 结构,只调用fetch操作。如果fetch可能失败,请将.catch()附加到.catch() .then()链并在那里处理。)

为什么父组件需要重新渲染? 你没有改变它的任何状态,因此没有理由重新渲染。 相反,您可以执行以下操作:

function MyComponent() {
    const [someState, setSomeState] = React.useState(defaultValue);

    console.log('Rendering with state', someState);

    // whatever asynchronous operation you want
    setTimeout(() => setSomeState(newValue), 1e3);

    return <p>{new Date()}</p>;
}

您将首先看到它使用defaultValue渲染一次,然后在一秒钟后使用newValue渲染。 使用useState钩子,每当您从某处更改状态时,它都会告诉 React “此组件的状态已更新,请重新渲染它”。

在您的情况下,您执行操作并使用需要组件重新渲染的结果执行某些操作的情况很少见,即使组件似乎实际上并未使用结果? 或者至少不是直接的。

对于您的组件,可以从localStorage读取defaultValue 并且每当您调用setSomeState ,您也可以直接将新值保存到localStorage 您的组件将能够直接使用该值,而无需在每次渲染时读取localStorage

那时你无权访问这个内部。 如果您使用如下箭头方法,您应该可以访问它。

submit = (e) => {
    e.preventDefault();
    const myInit1 = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*',
            'Vary': 'Origin'.replace,
            'Accept': 'application/json'
        },
        body: JSON.stringify({
            "username": this.state.username,
            "password": this.state.password,
            "email": this.state.email
        })
    };
    console.log(myInit1.body);
    let authurl = 'http://localhost:8080/authenticate';
    if(!!localStorage.getItem("token"))
    localStorage.removeItem("token");
    try {
        fetch(authurl, myInit1)
            .then((response) => {
                return response.json();
            })
            .then((myJson)=> {
                console.log(myJson.token);
                localStorage.setItem("token", myJson.token);
                console.log("isAuth " + !!localStorage.getItem("token"));    
            }).then();
            
    } catch (e) {

    }finally{
        this.props.rerenderParentCallback();
    }
    
}

这是使用异步等待执行此操作的另一种方法。

submit = async (e) => {
    e.preventDefault();
    const myInit1 = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*',
            'Vary': 'Origin'.replace,
            'Accept': 'application/json'
        },
        body: JSON.stringify({
            "username": this.state.username,
            "password": this.state.password,
            "email": this.state.email
        })
    };
    console.log(myInit1.body);
    let authurl = 'http://localhost:8080/authenticate';
    if(!!localStorage.getItem("token"))
    localStorage.removeItem("token");
    try {
       const response = await fetch(authurl, myInit1);
       const myJson = await response.json();

       console.log(myJson.token);
       localStorage.setItem("token", myJson.token);
       console.log("isAuth " + !!localStorage.getItem("token"));    
       /*
       * you may write it here
       * this.props.rerenderParentCallback();
       */     
    } catch (e) {

    }finally{
        this.props.rerenderParentCallback();
    }
    
} 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM