How react append div * num? - reactjs

class AddForm extends Component {
render() {
return (
<div>
asd
</div>
);
}
}
let addComponents = (num) => {
let i;
for(i = 0; i < num; i++) {
return (<AddForm />);
}
}
<div className="add">{ addComponents(this.state.addNum) }</div>
i want append asd * num
but asd is only one
this.state.addNum = 1
how react append asd * num?
Sorry, i am bad at english

Your function addComponent returns a single component, while it should actually return an array of components.
const addComponents = (num) => {
let arr = [];
for(let i = 0; i < num; i++) {
arr.push(<AddForm />);
}
return arr;
}

I am hoping that you want an output something like this..
if num = 3 then the output should be "asd asd asd"
The code for this will be :
class AddForm extends Component {
render() {
var str = "asd ";
for(var i=1; i<this.props.num; i++) {
str = str+ "asd ";
}
return (
<div>
{str}
</div>
);
}
}
let addComponents = (num) => {
return (<AddForm num={num} />);
}
<div className="add">{ addComponents(this.state.addNum) }</div>
If you are looking for an output something like this.. (asd * 3) if num = 3 then use the below code..
class AddForm extends Component {
render() {
return (
<div>
asd * {this.props.num}
</div>
);
}
}
let addComponents = (num) => {
return (<AddForm num={num} />);
}
<div className="add">{ addComponents(this.state.addNum) }</div>
In both the cases, you will understand that you need to pass the props to the child element and let the child element decide what it wants to render.
If you want the output something like this..
<div>asd</div>
<div>asd</div>
<div>asd</div>
Then the answer posted above by OB3 is correct.

Related

Append a component dynamically

I try to append a component dynamically, here it's Boards that i try to add to MainComponent.
The function addChild work and the list boards is filling up when the loop for is running, but nothing else happen, nothing is displayed on the screen
const MainComponent = props => (
<div className={props.className}>
<p>
<a href="#" onClick={props.addChild}>Add Another Child Component</a>
</p>
{props.boards}
</div>
);
class MainPage extends React.Component {
state = {
numChildren: 0
}
onAddChild = () => {
this.setState({
numChildren: this.state.numChildren + 1
});
}
render () {
const boards = [];
for (var i = 0; i < this.state.numChildren; i += 1) {
var _id = "board-" + i;
console.log
boards.push(<Board id={_id} className="board" />);
};
return (
<div className="test">
<Title/>
<MainComponent addChild={this.onAddChild} className="flexbox">
{boards}
</MainComponent>
</div>
);
}
}
export default MainPage```
Try to add key for each ChildComponent
const boards = [];
for (var i = 0; i < this.state.numChildren; i += 1) {
var _id = "board-" + i;
console.log
boards.push(<Board id={_id} key={_id} className="board" />);
};
because react depends on the key for rendering the component that is rendered inside loops
so react considers that all child that you are rendering is one component unless you give them a different key

Dynamic React Text Inputs

I am relatively new to React so sorry if this is a really easy/stupid question.
So I am making an app where you provide a number of months and depending on the number of months that number of text fields need to show up. Ex. 5 months = 5 new text fields. How would I go about doing that? I have tried various methods to no avail hence why I am asking here. Thank you for your help.
class MonthlyInputs extends React.Component {
render() {
let monthInputs = [1, 2, 3];
let items = [];
function updateInputs(event) {
monthInputs = [];
for (let i = 0; i < event.target.value; i++) {
monthInputs.push(i);
}
console.log(monthInputs)
for (let i = 0; i < monthInputs.length; i++) {
items.push(<li key={i}>list item {i}</li>);
}
}
for (const [index, value] of monthInputs.entries()) {
items.push(<li key={index}>{value}</li>)
}
return (
<div>
<input onChange={updateInputs} />
{items}
</div>
)
}
}
I attempted what you're trying to implement.
Let me know if you have any questions.
https://codesandbox.io/s/tender-liskov-iicor?fontsize=14&hidenavigation=1&theme=dark
Consider saving your variables in state. Also you shouldn't declare funcions in render funcion. Here is code:
class App extends Component{
constructor(){
super();
this.state = {
monthInputs: [],
}
}
updateInputs = (event) => {
let monthInputs = [];
for (let i = 0; i < event.target.value; i++) {
monthInputs.push(i);
}
this.setState({
monthInputs
})
}
render(){
const {monthInputs} = this.state;
return(
<div>
<input type="number" value={monthInputs} onChange={this.updateInputs} />
{monthInputs.length > 0 && monthInputs.map((number, index)=>
<li key={number}>{number}</li> )}
</div>
)
}
}
And here is link to codesandbox

Visualize the bubblesort

i'm trying to understand better react and algorithms so i decided to implement a visual bubbleSort.
Problem
I'm able to generate a random array of numbers + sort the values and display them...but
I cannot figure how to make the swap animation between two elements.
Code
import React, {Component} from 'react';
import './Chart.css';
class Chart extends Component {
state = {
columns: [],
buttonPressed: false,
}
bubbleSort = (inputArr) => {
let len = inputArr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len; j++) {
if (inputArr[j] > inputArr[j + 1]) {
let tmp = inputArr[j];
inputArr[j] = inputArr[j + 1];
inputArr[j + 1] = tmp;
}
}
}
return inputArr;
};
toggleOn = () =>{
this.setState({
columns: this.props.columns,
buttonPressed: !this.state.buttonPressed,
});
let numbers = this.props.columns;
this.bubbleSort(numbers);
}
render() {
//riformulare queste tre righe di codice
//sarebbe opportuno pensare ad un componente bar?
const numbers = this.props.columns;
const bar = numbers.map((number) =>
<div className="bar" style={{height: number+'px' }}>{number}</div>
);
return (
<div>
{numbers.length > 0 ?
<div>
<button className="sortButton" onClick={this.toggleOn}>Sort with Bubblesort</button>
<div className="chart">
{bar}
</div>
</div>
: null
}
</div>
);
}
}
export default Chart;
Considerations
1) the this.props.columns is an array filled of random numbers.
I saw something similar in this link, could you please give me a little help about some starting point ?
https://codepen.io/lonekorean/pen/bqjzqr
2) this is the repository where you will find all the components:
github repository

React render from a loop

I'm trying to do something very simple but its not playing well with my code. I can see it render but only 3 times and not 9
const renderTempBoxes = () => {
for (var i = 0; i < 10; i++) {
console.log('i = ', i);
return <div className={styles.box} key={i} />;
}
};
const Component = () => {
return (
{renderTempBoxes()}
)
}
This doesn't even work, which is overkill to use an array when I just want 9 boxes to render.
UPDATE:
const Component = () => {
return (
<div>
{
[...Array(10)].map((x, i) => {
console.log('i = ', i);
return <div className={styles.box} key={i} />;
})
}
</div>
)
}
The first issue is that you simply cannot return individual elements from within the for loop like that. This is not specific to React, this is simply a JavaScript issue. Instead you can try something like this using Array.from to map an array of elements:
const renderTempBoxes = () => Array.from({ length: 10 }).map((v, i) =>
<div className={styles.box} key={i}>{i}</div>
);
Or simply the for loop with Array.prototype.push to generate an array of elements and return it:
const renderTempBoxes = () => {
let els = [];
for (let i = 0; i < 10; i++) {
els.push(<div className={styles.box} key={i}>{i}</div>);
}
return els;
};
Rendering the elements:
const Component = () => {
return (
<div>
{renderTempBoxes()}
</div>
)
}
Or with React.Fragment to forgo the wrapping extra node:
const Component = () => {
return (
<React.Fragment>
{renderTempBoxes()}
</React.Fragment>
)
}
The second issue with your example is that <div /> isn't going to really render anything, it's not a void/self-closing element such as <meta />. Instead you would need to do return the div element as <div className={styles.box} key={i}>{whatever}</div>.
Regarding the syntax [...Array(10)], there must be an Webpack in terms of how it handles/transpiles Array(10), [...Array(10)], [...new Array(10)], or even `[...new Array(10).keys()]. Either of the approaches described in the answer should solve your issue.
I've created a StackBlitz to demonstrate the functionality.
When trying to render multiple times the same components use an array an map over it.
export default class MyComp extends Component {
constructor(props) {
super(props)
this.state = {
array: [{key: 1, props: {...}}, {key: 2, props: {...}, ...]
}
}
render () {
return (
<div>
{this.state.array.map((element) => {
return <div key={element.key} {...element.props}>
})}
</div>
)
}
}
Remember to always set a unique key to every component you render

Reactjs - want to print dynamic element

I am trying to create a dynamic element. whatever user input in an input box, the same number of LI element will create.
I get this output when I enter 2 in input box.
<li key=0>input 0</li><li key=1>input 1</li>
where I want two li elements.
import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
times: 0
};
}
createList = event => {
let times = event.target.value;
this.setState({
times
});
};
getData = times => {
let str = "";
for (let i = 0; i < times; i++) {
str += "<li key=" + i + ">input " + i + "</li>";
}
return <ul>{str}</ul>;
};
render() {
return (
<div className="App">
<p className="App-intro">
<input type="number" onChange={this.createList} />
{this.getData(this.state.times)}
</p>
</div>
);
}
}
export default App;
This is because you are treating them as string instead of DOM node elements. Use an array and push all the elements inside that and return the final result.
Don't forgot you are writing JSX, and <li> input: {i+1} </li> will get converted into:
React.createElement(
"li",
null,
"input: ",
i+1
);
But if you write: "<li>input: {i+1}</li>", it will be treated as a string.
Check the complied code result of these two cases by Babel REPL.
Solution:
Write it like this:
getData = times => {
let str = [];
for (let i = 0; i < times; i++) {
str.push(<li key={i}> input: {i+1} </li>);
}
return <ul>{str}</ul>;
};

Resources