1

I am trying to loop through multiple components in React. Essentially I would like the questions to loop through and transition similarly to the example for Lapsed User on https://iteratehq.com/.

Here is the main page that the components will loop in:

import React from 'react';
import Q1Name from './questions/Q1Name';
import Q2Birthday from './questions/Q2Birthday';
import Q3City from './questions/Q3City';
import Q4YouReady from './questions/Q4YouReady';
import Q5Setting from './questions/Q5Setting';
import Q6Length from './questions/Q6Length';
import Q7Email from './questions/Q7Email';



class SignUpPage extends React.Component {
    render() {
        const questions = [Q1Name, Q2Birthday, Q3City, Q4YouReady, Q5Setting, Q6Length, Q7Email];
        const QList = questions.map(function(question){
            return {question};
        });
        return (
            <div className = "container-fluid">
                <div className = "question-box">
                    <Q1Name />
                </div>
            </div>
        );
    }
}

export default SignUpPage;

The below is an example component I would like to bring in - note each question is slightly different. They take in name, email (with validation), city, birthday (date form), and various button answer options.

import React from 'react';

class Q1Name extends React.Component {
    render() {
        return (
            <div className="questions">
                <h1 id="question-h1">What is your name?</h1>
                <form>
                    <div className="form-group">
                        <input type="name" className="form-control text-form custom-form" id="yourNameHere" aria-describedby="name" placeholder="" />
                    </div>
                    <button type="submit" className="btn btn-custom btn-lg" onClick={console.log("hallo")}>Next Question!</button>
                </form>
            </div>
        );
    }
}

export default Q1Name;

I have been able to get everything else working except for this part. Any help would be greatly appreciated!!

2 Answers 2

5

Here is a simple demo of your requirement. The key is to just create a JSX element (<Component />) in a loop and then return the result via the render method.

class A extends React.Component {
  render() {
    return <div>I'm A, with {this.props.testProp}</div>;
  }
}

class B extends React.Component {
  render() {
    return <div>I'm B, with {this.props.testProp}</div>;
  }
}

class App extends React.Component {
  render() {
    const components = [A, B];
    const componentsToRender = components.map((Component, i) => (
      <Component key={i} testProp="testProp"/>
    ));
    return <div>{componentsToRender}</div>;
  }
}
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

Note the usage of a special key prop, when creating components in a loop. I've just used the index in the array for demo purposes, but it's recommended to use something that'll always be unique to that component. More on that here.

Sign up to request clarification or add additional context in comments.

4 Comments

So that definitely got me much closer!! It is now showing all elements on one page - Is there a trick to loop through them whenever the submit button is clicked.. ie: question 1: fill in name then submit => question 2 - submit => question 3? I assume it requires an onClick function
You mean you want to re-render all the questions every time a submit button is clicked?
yes, so essentially the user can only see one question at a time. My end goal is for the questions to transition in each time the next button is clicked.
One way you can accomplish this is to keep a currentQuestion in the state of your App component. Then, define a function in App which takes an index as a parameter and updates the currentQuestion state. Pass down this function as a prop to each of your questions and call it when you want to move to another question. Also, only render the question at the same same index as currrentQuestion.
3

React components are just functions. The JSX syntax is not something special, using <Component /> will compile to React.createElement(Component, null) (null because no props are being passed). The only special case are the components starting with lower case letter, for example <div />. These compile to React.createElement("div", null). This is true for any string you use, so be careful, <myCustomComponent /> will still compile into React.createElement("myCustomComponent", null), in turn creating a myCustomComponent DOM node, which most likely doesn't exist.

You can apply this knowledge to your case. You're already mapping through the list of your questions, all you need to change is the naming convention and render the questions:

const questions = [Q1Name, Q2Birthday, Q3City, Q4YouReady, Q5Setting, Q6Length, Q7Email];
const QList = questions.map(function(Question){
    return (<Question />);
});

Note: I like to add () around all the components, just to have some limits between JSX and regular JS code. I'm not sure if it's really needed in this case.

Alternatively, you can replace the return inside your current map function with:

return React.createElement(question, null);

Again, the null is for props value. If you want to pass some props, you can do that by passing an object instead of the null value. The passed object maps directly to this.props values inside the referenced question component. By the way, you can do the same with the above approach <Question prop1={prop1} prop2={prop2} /> will still work the same as it does with any other React component.

1 Comment

Thank you! That definitely helped a lot. Really appreciate the explanation :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.