Shammoo
Shammoo

Reputation: 1103

Best practice for conditional rendering of children elements in ReactJs with Redux connect?

The situation I have is a login screen that displays one of 3 blocks of code, depending on the store state of the app. Eg... Below would be the resulting render if the second display option was selected.

<LoginFormPage>
  <DisplayOption2 />
</LoginFormPage>

There are specific calls and logic for each display option distinct enough to warrant their own containers. My file structure is:

/components
  /displayOpt1.jsx
  /displayOpt2.jsx
  /displayOpt3.jsx
  /loginFormPage.jsx
/containers
  /displayOpt1.js
  /displayOpt2.js
  /displayOpt3.js
  /loginFormPage.js

I need a way to render the correct option without embedding too much logic into the parent container; since it really doesn't need to know anything about any of the login mechanisms. I can think of a few ways to do it.

  1. All logic in loginFormPage.js with a connect direct to the loginFormPage.jsx. Then conditional parameters in the loginFormPage.jsx that makes calls to the components directly; removing the other containers.
  2. Create a React.Component in the loginFormPage.js to do the conditional rendering calls to the other containers; this would call all the .jsx files from the container component. loginFormPage.jsx would then render the selected child with {props.children}.
  3. Same as 2. but do the conditional rendering call in the mergeProps parameter passed to connect in loginFormPage.js; rather than creating a jsx component in the container js code.
  4. Some standard practice that I don't know of?

Right now I'm leaning towards option 3, but I can't find any evidence with my Google searches of this being a recommended practice. All thoughts are welcome. Thanks.


Some code to maybe make it easier:

loginFormPage.jsx

<div>
  <div onClick={props.someActionHeader}>
    <h1>Login Form</h1>
  </div>
  <div className="formarea">
    // render the selected option here based on props.renderOptionChoice
    // this will be one of displayOpt1, displayOpt2, displayOpt3
  </div>
  <div className="otherstuff">...</div>
</div>

displayOpt1.jsx - Opt2.jsx and Opt3.jsx code is a variation of something like this

<div onClick={props.someAction1}>
  stuff...
</div>

loginFormPage.js

import LoginFormPage from '../components/loginFormPage'

const mapStateToProps = (state, ownProps) => {
  return {
    renderOptionChoice: state.login.selectedLoginType,
  }
}
const mapDispatchToProps = ...

export default connect(mapStateToProps, mapDispatchToProps)(LoginFormPage)

Upvotes: 0

Views: 1412

Answers (1)

Shammoo
Shammoo

Reputation: 1103

I can answer with what I've found to be the best practice. It's worth reading the 3 posts in my comment to the question.

The Container level should contain the What is being displayed. In terms of a Login screen with several different options, then all the What's should be presented in one file. Following this style makes it clear exactly What is being displayed on the particular screen / component simply by looking at a single file.

So at the top level, the render will look like:

render() {
    return (
        <LoginPage>
            {this.state.step === STEPS.Step1 && <LoginStep1 />}
            {this.state.step === STEPS.Step2 && <LoginStep2 />}
            {this.state.step === STEPS.Step3 && <LoginStep3 />}
        </LoginPage>
    )
}

Here LoginStep1/2/3 can be contained components with their own connection to the Redux state, or it can be managed at the LoginPage level if the steps code is very simple or strongly related.

Upvotes: 1

Related Questions