1

What implementation is needed to render different components from render method. As you can see below the idea is that Survey component receives an array which contains different components names (could be Input, CheckList, Dropdown, File). The array passes as property to Survey Component is generated properly depending of what button is clicked, but at the time to render different components is not working. I'm using JsComplete to test it.

const Dropdown = () =>{
  return(
    <div>
       <select>
          <option value="initial" selected>Select...</option>
          <option value="Option ">Option 1</option>
          <option value="Option ">Option 2</option>
        </select>
    </div>
  )
}

const Checklist = () =>{
  return(
    <div>
        <h4>Question name</h4>
        <label>
          Option 1:
          <input
            name="pl"
            type="checkbox" />
        </label>
        <label>
          Option 2:
          <input
            name="tz"
            type="checkbox" />
        </label>
    </div>
  )
}

const Input = () =>{
  return(
    <div>
        <label>
          Question name: 
          <input
            name="input"
            type="text" />
        </label>
    </div>
  )
}

const File = () =>{
  return(
    <div>
        <label>
          Upload: 
          <input
            name="file"
            type="file" />
        </label>
    </div>
  )
}

class Survey extends React.Component {
  constructor(props){
    super(props);
  }

  render(){
    var ChildName ;

    for (var i = 0; i < this.props.components.length; i++) {    
       log("Log:" + this.props.components[i]);  
       ChildName = this.props.components[i];
       return <ChildName />;
    }          

    return (
       false
    )
  }
}    

class Form extends React.Component {

  handleSubmit = (name) => {    
    this.props.onSubmit(name);        
  };

  render() {
    return (
      <div id="components">
        <button onClick={()=>this.handleSubmit("Input")} name="Input">Input</button>
        <button onClick={()=>this.handleSubmit("Checklist")} name="Checklist">Checkbox</button>
        <button onClick={()=>this.handleSubmit("Dropdown")} name="Dropdown">Dropdown</button>
        <button onClick={()=>this.handleSubmit("File")} name="File">File</button>
        <div id="new-question">    
        </div>  
      </div>

    )
  }
}

class App extends React.Component {
  state = {
    components: []
  };

  addNewElement = (element) => {
    this.setState(prevState => ({
      components: prevState.components.concat(element)
    }));
  };

  render() {
    return (
      <div>
        <Form onSubmit={this.addNewElement} />
        <Survey components={this.state.components} />          
      </div>
    );
  }
}

ReactDOM.render(<App />, mountNode);

3 Answers 3

1

Try this. Dont pass string in handleSubmit method. Instead pass component itself like this:

class Form extends React.Component {

  handleSubmit = (name) => {    
    this.props.onSubmit(name);        
  };

  render() {
    return (
      <div id="components">
        <button onClick={()=>this.handleSubmit(Input)} name="Input">Input</button>
        <button onClick={()=>this.handleSubmit(Checklist)} name="Checklist">Checkbox</button>
        <button onClick={()=>this.handleSubmit(Dropdown)} name="Dropdown">Dropdown</button>
        <button onClick={()=>this.handleSubmit(File)} name="File">File</button>
        <div id="new-question">    
        </div>  
      </div>

    )
  }
}

Also in you survey component return the elements like this

class Survey extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {

        if (this.props.components.length === 0) {
            return null;
        }
        const renderCommpos = this.props.components.map((Elem, index) => {
            return <Elem key={index} />
        });

        return (
            <div>
                {renderCommpos}
            </div>
        );

    }
}

Also notice the Elem in map function. When it comes to react component jsx needs the first letter capital. So doesn't matter what variable you keep at place of Elem, you should always keep the first letter capital.

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

Comments

0

The render method for your survey component should be like this :

render(){
  const { components } = this.props;

  return (
    <div>
      {
        components.map((c, index) => {
          return (
            <div key={`one-of-components-${index}`}>
              {c}
            </div>
          );
        })
      }
    </div>
  );
}

Now it will return all the components in the props.

2 Comments

It only prints to me the name of button clicked which is the correct Component that I need to render, there's a way to instead of that render the html from the Component printed ?
In your addNewElement method, the element you are passing is a string. You will need to create an object that has the string names as keys and the components as the value of the keys so that you can get the actual component from a string value.
0

Try this out.

const Survey = ({ components }) => {
    const Components = components.map(
        ( component, index ) => {
            return (
                <div key={ index }>
                    { component }
                </div>
            );
        }
    );

    return (
        <div>
            { Components }
        </div>
    );
};

In your for loop you're returning from the function on the first component. Add them to an array and then return the array. On another note, I used a functional stateless component here. I don't see the need for the class overhead.

Comments

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.