用数据初始化useState并没有刷新页面。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用数据初始化useState并没有刷新页面。相关的知识,希望对你有一定的参考价值。

我有一条路线。

<Route path="/projects/:handle" component={Project} />

当我浏览到i. e. ,页面加载成功 /projects/my-project-1的时候,页面加载成功,但是如果我到了 /projects/my-other-project,页面的内容保持不变(我的项目-1内容)。

match.params.handle 获取的数据,但useState仍然保留了(my-project-1)的数据。

const Project = ({ match }) => {

   const projectContext = useContext(ProjectContext)
   const [project] = useState(projectContext.getProject(match.params.handle))

   // my-other-project
   console.log(match.params.handle);

   let proj = projectContext.getProject(match.params.handle);

   // returns my-other-project
   console.log(proj)

   const [project] = useState(proj)

   // this is still my-project-1 data
   console.log(project);

   return (
       <>
        <Row>
            <Col sm={12} lg={12}>
                <ProjectOverview projectContext={projectContext} project={project} />
            </Col>
        </Row>
    </>
   );
}

export default Project;

我加载组件数据的方式可能有什么问题,有没有更好的方法,也许是通过useEffect?有点儿 新的反应(和反应钩子))

答案

这不是你使用道具初始化状态的方式(我们将在一分钟内回到这个问题)。

一般来说,没有理由把道具复制到状态。只要使用道具就可以了。这就是它的作用。它基本上是你组件的状态,由父组件管理。所以。

const Project = ({ match }) => {

    const projectContext = useContext(ProjectContext)
    const project = projectContext.getProject(match.params.handle); // ***

    return (
        <>
            <Row>
                <Col sm={12} lg={12}>
                    <ProjectOverview projectContext={projectContext} project={project} />
                </Col>
            </Row>
        </>
    );
}

(附注: 没有必要使用那个片段,你可以返回这个片段) Row 直接)。)

如果 projectContext.getProject(match.params.handle) 是一个昂贵的操作,你可以通过以下方式来记忆 useMemo:

const Project = ({ match }) => {

    const projectContext = useContext(ProjectContext)
    const project = useMemo(
        () => projectContext.getProject(match.params.handle),
        [match.params.handle]
    );

    return (
        <>
            <Row>
                <Col sm={12} lg={12}>
                    <ProjectOverview projectContext={projectContext} project={project} />
                </Col>
            </Row>
        </>
    );
}

实例。

const { useState, useEffect, useMemo, useContext } = React;

const Row = props => <div {...props}/>;
const Col = props => <div {...props}/>;
const ProjectOverview = ({projectContext, project}) => {
    return <div>Project: {project.name}</div>;
};

const contextValue = {
    getProject(handle) {
        console.log(`Getting project ${handle}...`);
        // busy-wait half a second
        const end = Date.now() + 500;
        while (Date.now < end) {
            // Wait -- NEVER BUSY WAIT LIKE THIS IN REAL CODE
        }
        return {name: `Project for handle ${handle}`};
    }
};
const ProjectContext = React.createContext(contextValue);

const Project = ({ match }) => {
    console.log(`Project called with handle = ${match.params.handle}`);

    const projectContext = useContext(ProjectContext)
    const project = useMemo(
        () => {
            console.log(`Recalcuating project from handle ${match.params.handle}`);
            return projectContext.getProject(match.params.handle);
        },
        [match.params.handle]
    );

    console.log(`project is: "${project.name}"`);
   
    // Note: Can't use <>...</> in Stack Snippets, we have
    // to use the older React.Fragment syntax.
    return (
        <React.Fragment>
            <Row>
                <Col sm={12} lg={12}>
                    <ProjectOverview projectContext={projectContext} project={project} />
                </Col>
            </Row>
        </React.Fragment>
    );
}

const App = () => {
    const [counter, setCounter] = useState(0);
    const [handle, setHandle] = useState(1);
    
    useEffect(() => {
        if (handle < 3) {
            setTimeout(() => {
                setCounter(c => {
                    c = c == 0 ? 1 : 0;
                    if (c == 0) {
                        // Update the handle every two calls
                        setHandle(h => h + 1);
                    }
                    return c;
                });
            }, 800);
        }
    }, [handle, counter]);

    return (
        <ProjectContext.Provider value={contextValue}>
            <Project match={{params: {handle}}} />
        </ProjectContext.Provider>
    );
};

ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

以上是关于用数据初始化useState并没有刷新页面。的主要内容,如果未能解决你的问题,请参考以下文章

React Hook useState 视图不更新

Vue 刷新页面时会触发事件吗

ajax执行action,怎么没有刷新页面数据,要自己刷新一下页面数据才出来?

用JS怎么实现刷新页面后保留刷新前的页面上的数据显示

useState 设置方法不会立即反映更改

反应 useState 钩子不使用 axios 调用更新