Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing Views in ReactJS

Tags:

reactjs

I have not been using ReactJS for very long. I have a situation that I think must be very common, but I’ve not seen it addressed in any examples, and I’d like to know if there are any best practices involved.

The scenario is simply that say I have 3 forms in my application, FormA, FormB, and FormC. I have written each form as a separate ReactJS component. When the user lands on the site, FormA is displayed. Depending on the input on FormA, then either FormB or FormC will be displayed next, completely replacing FormA on the page.

I don’t think “routing” is the answer because I don’t want the URL to reflect the current application state, and I don’t want the user to be able to change forms by changing the URL. The switching of forms (components) should be done based only on business rules.

I know ReactJS is not a framework, but this seems like a common enough scenario that some useful patterns have probably evolved around it. Just a nudge in the right direction would be very helpful. Thank you.

like image 680
ItsCosmo Avatar asked Feb 18 '16 15:02

ItsCosmo


People also ask

What are views in react JS?

The View is the fundamental component of React Native for building a user interface. It is a container that supports layout with flexbox, style, touch handling, and accessibility controls. It maps directly to the native view similar to whatever platform on React Native app is running on.

Is it OK to use window object in React?

The window object is the normal DOM object. It is always available and safe to use (unless you are server side rendering).

Can you change React props?

A component cannot update its own props unless they are arrays or objects (having a component update its own props even if possible is an anti-pattern), but can update its state and the props of its children.

What is shouldComponentUpdate in React?

The shouldComponentUpdate is a lifecycle method in React. This method makes the component to re-render only when there is a change in state or props of a component and that change will affect the output.


2 Answers

The solution is to create wrapper Form component that contains FormA, FormB, FormC and show one of them depends on its state. Like

const Form = React.createComponent({

  getInitialState() {
    return {
      form: 'formA'
      /* other state */
    }
  },

  render() {
    return (
      <div>
        {this.state.form === 'formA' ? <FormA onSubmit={this.saveFormData} /> : null}
        {this.state.form === 'formB' ? <FormB onSubmit={this.saveFormData} /> : null}
        {this.state.form === 'formC' ? <FormC onSubmit={this.saveFormData} /> : null}
      </div>
    )
  },

  saveFromData() {
    /* set state here */
  }

})

Such delegation is common for React. Normally you should manage your forms logic in the Form and FormA, FormB, FormC should be dumb components that can only execute functions from passed props.

Note that example code listing above is just a demonstration. Usually you don't need to keep form in state. Instead there can be i. e. username, password, email (or anything) and you should check what form to show based on this state values.

like image 104
Glen Swift Avatar answered Oct 21 '22 23:10

Glen Swift


Here's a very simple solution creating a SwitchComponents component:

// SwitchComponents.js:

import React from 'react';

export default function SwitchComponents({ active, children }) {
  // Switch all children and return the "active" one
  return children.filter(child => child.props.name == active)
}

And import it in your app:

// App.js
import SwitchComponents from './components/SwitchComponents';

export default function App() {

const [activeComponent, setActiveComponent] = useState("questions")

return (
    <SwitchComponents active={activeComponent}>
      <Home name="home" />
      <Instructions name="instructions" />
      <FileboxContainer name="filebox" />
      <Questions name="questions" />
    </SwitchComponents>
  )
}

If you don't wanna pass the "name" property, you can you the solution below:

return children.filter(child => child.type.name == active)

But that's the name you give to your function when you define you component, like this:

export default function MyFunctionName() { ... } // this is the name

Even if you import it with another name, that's still gonna be the name you must use.

like image 2
Maycow Moura Avatar answered Oct 21 '22 23:10

Maycow Moura