【问题标题】:React state in different component on different page route在不同页面路由上的不同组件中反应状态
【发布时间】:2019-03-07 22:54:15
【问题描述】:

我已经能够在名为SubmitProject 的特定组件上设置状态,该组件位于特定路线/submit。现在我还有一个路由/portfolio,它有一个名为Portfolio 的组件我想知道如何让SubmitProject 的状态与Portfolio 上的状态相同你只能与嵌套在每个组件中的组件共享状态吗其他。我最终要做的是使用表单提交文本以在/submit 路由上进行状态,然后在/portfolio 路由中更新相同的状态数据。

我可能在设计上出现了错误,如果一切都在 APP 组件中并且我做的路由不同,我对 React 还是很陌生,所以我肯定需要有关如何设置我的项目的指导。

好的,提前谢谢。

这是我的相关代码

src/components/SubmitProject.js

import React from 'react';
import PortfolioForm from './PortfolioForm';

class SubmitProject extends React.Component {
    state = {
        sections:{}
    };
    addSection = section =>{
        const sections = {...this.state.sections};
        sections[`section${Date.now()}`] = section;
        this.setState({
            sections: sections
        });
    }
    render() {
        return(
            <React.Fragment>
                <h1>Submit Project</h1>
                <h2>Enter Project Data</h2>
                <PortfolioForm addSection={this.addSection} />
            </React.Fragment>
        )
    }
}

export default SubmitProject;

src/components/PortfolioForm.js

import React from 'react';
import FormAdd from './FormAdd';

class Portfolio extends React.Component {
    render() {
        return(
            <React.Fragment>
                <h1>Submit Form</h1>
                <FormAdd addSection={this.props.addSection}/>
            </React.Fragment>
        )
    }
}

export default Portfolio;

src/components/FormAdd.js

import React from 'react';

class FormAdd extends React.Component {
    nameRef = React.createRef();

    createSection = (event) =>{
        event.preventDefault();
        const section = {
            name: this.nameRef.current.value
        };
        this.props.addSection(section);
    };  
    render() {
        return(
            <React.Fragment>
                <form onSubmit={this.createSection}>
                    <input type="text" ref={this.nameRef} name="name" placeholder="Name"/>
                    <button type="submit">+ Add Section</button>
                </form>
            </React.Fragment>
        )
    }
}

export default FormAdd;

src/components/Router.js

import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import Portfolio from './Portfolio';
import SubmitProject from './SubmitProject';
import App from './App';

const Router = () => (
    <BrowserRouter>
        <Switch>
            <Route exact path="/" component={App}/>
            <Route exact path="/portfolio" component={Portfolio}/>
            <Route exact path="/submit" component={SubmitProject}/>
        </Switch>
    </BrowserRouter>
);

export default Router;

src/Portfolio.js

import React from 'react';

class Portfolio extends React.Component {
    //CAN I GET STATE FROM SubmitProject.js FILE IN HERE?
    render() {
        return(
            <React.Fragment>
                <h1>Portfolio Page</h1>
                <h2>List of projects</h2>        
            </React.Fragment>
        )
    }
}

export default Portfolio;

【问题讨论】:

  • 像 redux/mobx 这样的外部化状态管理解决方案,或者 react 的 context api 可以解决这个问题 - 你熟悉这些吗?

标签: javascript reactjs state


【解决方案1】:

如果您使用的是 React 16,那么您可以使用 Context API 解决此问题。这将涉及对您的代码进行以下调整:

// PortfolioContext.jsx
// Define a PortfolioContext component with initial shared 'sections' state
export default const PortfolioContext = React.createContext(
  sections : {}
);

然后更新您的 SubmitProject 组件以使用PortfolioContext 组件来更新共享的sections 状态:

// SubmitProject.jsx
// Use the ProtfolioContext component in your SubmitProject component to update
// the shared for use in the Portfolio component
import React from 'react';
import PortfolioForm from './PortfolioForm';
import PortfolioContext from './PortfolioContext';

class SubmitProject extends React.Component {
   constructor (props) {
        super(props)
        this.state = {
             sections:{}
        };
    }

    addSection = section =>{
        const sections = {...this.state.sections};
        sections[`section${Date.now()}`] = section;
        this.setState({
            sections: sections
        });
    }
    render() {
        return(
            { /* Inject the local sections state into provider */ }
            <PortfolioContext.Provider value={this.state.sections}>
                <React.Fragment>
                    <h1>Submit Project</h1>
                    <h2>Enter Project Data</h2>
                    <PortfolioForm addSection={this.addSection} />
                </React.Fragment>
            </PortfolioContext.Provider>
        )
    }
}

export default SubmitProject;

同时更新您的 Portfolio 组件以使用 PortfolioContext 组件来获取共享状态:

// Portfolio.jsx
import React from 'react';
import PortfolioContext from './PortfolioContext';

class Portfolio extends React.Component {
    //CAN I GET STATE FROM SubmitProject.js FILE IN HERE?
    render() {
        return(
            { /* Use the PortfolioContext.Consumer to access sections state */}
            <PortfolioContext.Consumer>
            {
                sections => (
                    <React.Fragment>
                        <h1>Portfolio Page</h1>
                        <h2>List of projects</h2>        
                        { /* here is the shared state - access and render section data as needed. This is just a demonstration to show how the data can be rendered in some way */ }
                        { Object.values(sections || {}).map(section => (<p>JSON.stringify(section)</p>) )}
                    </React.Fragment>
                )
            }
             </PortfolioContext.Consumer>
        )
    }
}

export default Portfolio;

希望有帮助!

【讨论】:

  • 你认为这是一个好主意,还是我应该重写我的代码,让一切都在 App 中,我可以通过 props 传递状态。在引用上下文 api 的反应文档中,它说 Apply it sparingly because it makes component reuse more difficult.
  • 确实如此 - 这真的取决于您的项目细节。如果您可以通过道具传递状态来获得相同的结果,那么这可能是更好的方法。如果你有一个很深的组件层次结构,那么从层次结构的顶部到底部传递道具可能很难维护,在这种情况下,基于上下文的方法可能会更好。
  • 所以我的编辑器在sections: {}, 中强调了: 那个代码有问题吗?
  • 我想是因为你错过了{},就像export const PortfolioContext = React.createContext({ sections : {} });
猜你喜欢
  • 2023-03-05
  • 2018-09-30
  • 2020-07-24
  • 2018-11-17
  • 1970-01-01
  • 2023-03-26
  • 2023-01-21
  • 2020-10-17
  • 2017-08-11
相关资源
最近更新 更多