简体   繁体   中英

React state in different component on different page route

I have been able to setState on a specific component called SubmitProject which lives at a specific route /submit . Now I also have a route /portfolio that has a component called Portfolio I am wondering how do I get the state from SubmitProject to be the same on Portfolio Can you only share state with Components that are nested within each other. What I am ultimately trying to do is use a form to submit text to state on the /submit route and then have that same state data update in the /portfolio route.

I could be approaching the design wrong, Should everything maybe be in APP Component and I do the Routing different, I am very new to React, so I defintely need guidance on how to setup my project.

Ok Thanks ahead of time.

Here is my relevant code

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;

If you're using React 16, then you could resolve this by using the Context API. This would involve making the following adjustments to your code:

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

Then update your SubmitProject component to use the PortfolioContext component to update the shared sections state:

// 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;

And also update your Portfolio component to use the PortfolioContext component to get the shared state:

// 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;

Hope that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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