Reputation: 499
On reactjs how does one print one element per second from an array? I have tried to replicate and simplify my work. The array comes from redux. But the final situation doesn't change. Thanks.
const arrWords=["I", "would", "like", "to", "print", "one", "word", "per", "second"];
class Message extends React.Component {
renderWord(word,index) {
return <span key={index}> {word} </span>;
}
renderWords() {
const words = arrWords.map((word, index) => {
return this.renderWord(word, index);
});
return words;
}
render(){
return (
<p>{this.renderWords()}</p>
);
}
};
ReactDOM.render(<Message />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>
Upvotes: 1
Views: 334
Reputation: 7658
The answers above aren't incorrect but they aren't very fun either.
Use Promise.resolve()
to solve this.
not too sure if you mean render one word per second by replacing the previous each time, or one word per second by appending to the end
const arrWords=["I", "would", "like", "to", "print", "one", "word", "per", "second"];
class Message extends React.Component {
state = { word: '', index: 0 };
renderWord(word,index) {
return new Promise(( resolve, reject ) => {
if ( this.wordTimeout ) clearTimeout(this.wordTimeout);
this.wordTimeout = setTimeout(() =>
this.setState({ word, index }, resolve),
1000
)
});
}
componentDidMount () {
arrWords.reduce(( promise, word, index ) =>
promise.then(() => this.renderWord(word, index)),
Promise.resolve()
);
}
render(){
return (
<p>
<span key={this.state.index}> {this.state.word} </span>
</p>
);
}
};
ReactDOM.render(<Message />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>
const arrWords=["I", "would", "like", "to", "print", "one", "word", "per", "second"];
class Message extends React.Component {
state = { index: 0 };
renderSentence (index) {
return new Promise(( resolve, reject ) => {
if ( this.wordTimeout ) clearTimeout(this.wordTimeout);
this.wordTimeout = setTimeout(() =>
this.setState({ index }, resolve),
1000
)
});
}
componentDidMount () {
arrWords.reduce(( promise, word, index ) =>
promise.then(() => this.renderSentence(index)),
Promise.resolve()
);
}
render(){
// Plenty of better ways to do this but this will do what you need
const words = arrWords.slice(0, this.state.index + 1);
const renderedWords = words.map(word =>
<span key={`${this.state.index}-${word}`}> {word} </span>
);
return (
<p>
{renderedWords}
</p>
);
}
};
ReactDOM.render(<Message />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>
Upvotes: 1
Reputation: 6868
I think this should work for you. Use the React lifecycle methods to start and end an interval before the component mounts and unmount. Simply increment the index and let React handle the rest.
const arrWords = ["I", "would", "like", "to", "print", "one", "word", "per", "second"];
class Message extends React.Component {
constructor() {
super();
this.state = {
arr: arrWords,
index: 0
}
}
componentDidMount() {
this.timer = setInterval(() => {
const { index, arr } = this.state;
// increment index if appropriate or reset to 0
this.setState({ index: index + 1 >= arr.length ? 0 : index + 1});
}, 1000);
}
// Clean up before unmounting
componentWillUnmount() {
clearInterval(this.timer);
}
render() {
const { arr, index} = this.state;
return <p>{arr[index]}</p>;
}
}
ReactDOM.render(<Message />, document.getElementById("app"));
Upvotes: 1
Reputation: 281646
One possible solution is to keep an index
that keeps incrementing every second and render that many words
const arrWords=["I", "would", "like", "to", "print", "one", "word", "per", "second"];
class Message extends React.Component {
state = {
count: 0
};
componentDidMount() {
this.timerID = setInterval(()=> {
console.log(this.state);
this.setState(prevState => ({
count: (prevState.count + 1)%arrWords.length
}))
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
renderWord(word,index) {
return <span key={index}> {word} </span>;
}
renderWords() {
const words = arrWords.map((word, index) => {
if(index <= this.state.count)
return this.renderWord(word, index);
});
return words;
}
render(){
return (
<p>{this.renderWords()}</p>
);
}
};
ReactDOM.render(<Message />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>
Upvotes: 3