i am absolutely begginner in react so please forgive me , i am stuck with Dynamic content creation , i cant make increment in top property , after render where i am using map and i am using top property , i dont know how to increase the num , i have tried in setstate but it does not work each time , it happens before render , and i only see pics at the last location
class People extends React.Component {
componentDidMount = () => {
//$('#Dynamic').hide()
}
constructor(props){
super(props);
this.state = {
Info : []
}
var Ref = firebase.database().ref('Users');
Ref.once('value' , (i) => {
i.forEach((y)=>{
var data = y.val()
myArray[c] = data.Photo;
// alert(myArray[c]) ;
c++ ;
this.setState({
Info : myArray
})
})
})
}
render () {
n += 100;
return (
<div>
<div id = 'Dynamic' >
<div id = 'hi'> { this.state.Info.map(i =>
{ return <img style = {{'top' : n }} className = 'public' src = {i} /> }
)}
</div>
</div>
</div>
);
}
}
export default People
setState() does not immediately mutate this.state but creates a pending state transition. So, no multiple rendering while calling setState in a loop.
Related
I'm trying to use the onMouseDown event in react to change the text but it doesn't work.
I saw a similar code which actually worked so I have no idea what could be wrong.
import React, { Component } from "react";
import "./ContentComponent.css";
class Content extends Component{
constructor(){
super()
this.onClickForward = this.onClickForward.bind(this)
this.onClickBack = this.onClickBack.bind(this)
const img0 = require('./images/dog1.jpg');
const img1 = require('./images/dog2.jpg');
const img2 = require('./images/dog3.jpg');
const img3 = require('./images/dog4.jpg');
this.state={
index: 0,
imgList: [img0, img1, img2, img3]
}
this.state2 = {
tekst: "Pies"
}
}
onClickForward(){
if (this.state.index + 1 === this.state.imgList.lenght) {
this.setState({
index: 0
})
} else{
this.setState({
index: this.state.index +1
})
}
}
onClickBack(){
if (this.state.index - 1 === -1) {
this.setState({
index: this.state.imgList.lenght -1
})
} else{
this.setState({
index: this.state.index - 1
})
}
}
zmianaTekstu() {
this.setState2({
tekst: "Pies domowy - udomowiony gatunek ssaka drapieżnego z rodziny psowatych, traktowany przez niektóre ujęcia systematyczne za podgatunek wilka."
})
}
render(){
return(
<div className="info">
<img src={this.state.imgList[this.state.index]} alt="" className="mainImage" />
<div className="btns">
<button onClick={this.onClickBack}>Poprzednie</button>
<button onClick={this.onClickForward}>Następne</button>
</div>
<div className="textInfo">
<h3 onMouseDown={() => this.zmianaTekstu()}>Click to change text</h3>
<p>{this.state2.tekst}</p>
</div>
</div>
)
}
}
export default Content;
Console says
Uncaught TypeError: this.setState2 is not a function
The first state which changes images on button click actually works but I've pasted the whole code since maybe there is some interaction.
You should use only one react's state in Class Component, in that way can access the setState and Update it. A state is an object so it can contain inside of it more variables, arrays, or even more objects. just hold inside the same state, variable for tekst
and update it like you update the first state, like so:
this.state = {
index: 0,
imgList: [img0, img1, img2, img3],
tekst: 'pies',
}
And then update the state whenever you need, like so:
this.setState({
tekst: "Pies domowy - udomowiony gatunek ssaka drapieżnego z rodziny psowatych, traktowany przez niektóre ujęcia systematyczne za podgatunek wilka."
})
the setState method is specific to your component, you cannot use another method to modify another state in your component, you could put all your data in the first state object or also use state hooks ?
I am new to reactJS. I want to create a component to change background images dynamically. I just write a javascript to update background image every 5 seconds but it doesn't work. These images are local images, I want to loop them and display them. Would you please take a look? Thank you very much!
import * as React from 'react';
import * as image from './resources';
const TIME_TICK_PERIOD = 5000;
var images =['resources/yellowstone.jpg','resources/yellowstone2.jpg','resources/yellowstone3.jpg'];
export class BackgroundImage extends React.Component {
constructor(props) {
super(props);
this.state = {
index:0
};
}
componentDidMount() {
this.timerID = setInterval(() => this.tick(), TIME_TICK_PERIOD);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
let idx = this.state.index;
if(idx >=images.length-1) {
this.setState({
index: 0
});
} else {
this.setState({
index: idx+1
})
}
}
render() {
return (
<div className="hints-on-home-screen">
<div
style={{
position: absolute,
backgroundImage: `url(${images[this.state.index]}`)
}}
/>
</div>
);
}
}
You are saving your initial index of 0 outside the component scope. So index + 1 is always evaluating to 1. Instead of saving the imagePath in your state, save the index in your state. Then increment it in tick. Then reference images[index].
I'm trying to create a UI that allows users to download files from their computer to create an audio playlist. I'm trying to append a child that I created in my javascript code using const li = <li ref={this.liRef}></li>. For some reason this won't work when I try to append it with ulRefNode.appendChild(li); and ulRefNode.appendChild(liNode);. The const liNode also returns null. Are li and liNode node elements? Here's the code:
class Download extends React.Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this);
this.inputRef = React.createRef();
this.ulRef = React.createRef();
this.destinationRef = React.createRef();
this.liRef = React.createRef();
}
handleClick = () => {
const node = this.inputRef.current;
const destNode = this.destinationRef.current;
const ulRefNode = this.ulRef.current;
const liNode = this.liRef.current;
node.addEventListener('change', function() {
var file;
var ulAlreadyAdded = true;
for(var x = 0, xlen = this.files.length; x < xlen; x++) {
console.log(this.files[x]);
file = this.files[x];
var reader = new FileReader();
reader.onload = (e) => {
const li = <li ref={this.liRef}></li>
console.log("LINODE " + liNode);
ulRefNode.appendChild(liNode);
}
reader.readAsDataURL(file);
};
});
};
render() {
return(
<div className="input">
<input onClick={this.handleClick} id="upload-file" className="inputName" type="file" multiple ref={this.inputRef}/>
<ReactAudioPlayer
src="my_audio_file.ogg"
autoPlay
controls
/>
<div ref={this.destinationRef} id="destinationID"></div>
<ul ref={this.ulRef}></ul>
<output id="list"></output>
</div>
)
};
}
export default Download;
As far as I can tell, what you're trying to achieve is not meant to be done like that using React.
In React you should (in this case), read the data from whatever source you need, load it into state, and then render the UI you want to show the user.
I would suggest taking a look at the React tutorial before proceeding: https://reactjs.org/tutorial/tutorial.html
To give a quick idea about what the React component might look like, I've put together a small example:
import React from 'react';
class Download extends React.Component {
constructor(props) {
super(props);
this.state = {
files: [],
};
}
componentDidMount {
// Fetch your data (possibly asynchronously) and
// update the component state, which will cause
// the component to re-render
this.setState({
files: [{ name: 'File A' }, { name: 'File B' }],
});
}
render() {
return (
<ul>
{this.state.files.map((file, index) => (
<li key={index}>
{file.name}
</li>
))}
</ul>
);
}
}
Note for whomever might stumble upon this: Beware, that I've used some practices in this code snippet that might not be considered best practices, but helps simplify the explanation of the code (e.g. how setState is used and using an index as key in the render method's loop.
I'm new to React. As a learning exercise I'm building an chess application
I want to change the DOM of child based on state in parent. Currently there is no change in child components on change of state in parent.
Parent Component
class Game extends Component{
constructor(){
super();
this.state = {
game :{
board_position = { 'One' : ''}
}
}
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
let p = this.state.game.board_position;
// some computations on p
p = { board_position : { 'One' : Math.random() } }
this.setState({
game : p
})
//this.forceUpdate(); // Just trying different methods to make it work
}
render(){
return(
<div onClick={(e) => this.handleClick(e) }>
<Piece {...this.state.game.board_position} />
</div>
)
}
}
Child Component
Class Piece extends Component{
constructor(){
super(props);
this.state = {
clr : ''
}
}
componentWillMount(){
let c;
// some computations that change value of c based on props
if( typeof ( this.props.game.one) == number ){
c = 'Red'
} else {
c = 'Blue'
}
this.setState({
clr : c
})
}
render(){
return(
<span>{this.state.clr}</span>
)
}
}
On call of handle click method, there is a change in state of the game. However, subsequent changes in Child are not seen.
Can anyone please help me out? Where am I going wrong?
I'm not sure how to implement ref as suggested over here. However, I don't think that is a good solution. Probably I'm having some conceptual misunderstanding.
PS: Please ignore any syntax error. This code is a strip down of real code.
If you want to take a look at full code - go over here
componentWillMount in your Piece component will only fire once.
Are you updating your state each time the props change as well ? For example using componentWillReceiveProps
Also you could just display the props directly in your render function
render(){
return(
<span>{use the props directly here}</span>
)
}
Try to avoid using state whenever possible, and stick with just rendering your component based on props.
it's a pretty basic react process:
class Game extends Component{
constructor(){
super();
this.state = {
game :{
board_position = { 'One' : ''}
}
}
this.handleClick = this.handleClick.bind(this);
}
handleClick(e){
let p = this.state.game.board_position;
// some computations on p
p = { board_position : { 'One' : Math.random() } }
this.setState({
game : p
})
}
render(){
return(
<div onClick={this.handleClick}>
<Piece board_position={this.state.game.board_position} />
</div>
)
}
}
Child: //can be a function instead of a class
const Piece = ({board_position}) =>{
const {board_position} = this.props;
let clt = board_position;
//do some stuff
return(
<span>{board_position}</span>
);
};
if you want to do more calculations you can use componentWillReceiveProps(newProps)
A component re render when it's props or states get changed. There will be certain life cycle methods get invoked based on the values of props and own states.
The way you accessed your **props is wrong.**
It should be
this.props.One
Life cycle method you should have used is componentWillReciveProps(nextProps). In that case you should access the relevant prop like below
nextProps.One
I have created a working fiddle (your code had errors if you fixed those and looked at your log you could have easily figure out where the error is)
I have a react component that I wish to populate with images using the Dropbox api. The api part works fine, but the component is rendered before the data comes through & so the array is empty. How can I delay the rendering of the component until it has the data it needs?
var fileList = [];
var images = [];
var imageSource = [];
class Foo extends React.Component {
render(){
dbx.filesListFolder({path: ''})
.then(function(response) {
fileList=response.entries;
for(var i=0; i<fileList.length; i++){
imageSource.push(fileList[0].path_lower);
}
console.log(imageSource);
})
for(var a=0; a<imageSource.length; a++){
images.push(<img key={a} className='images'/>);
}
return (
<div className="folioWrapper">
{images}
</div>
);
}
}
Thanks for your help!
Changes:
1. Don't do the api call inside render method, use componentDidMount lifecycle method for that.
componentDidMount:
componentDidMount() is invoked immediately after a component is
mounted. Initialization that requires DOM nodes should go here. If you
need to load data from a remote endpoint, this is a good place to
instantiate the network request. Setting state in this method will
trigger a re-rendering.
2. Define the imageSource variable in state array with initial value [], once you get the response update that using setState, it will automatically re-render the component with updated data.
3. Use the state array to generate the ui components in render method.
4. To hold the rendering until you didn't get the data, put the condition inside render method check the length of imageSource array if length is zero then return null.
Write it like this:
class Foo extends React.Component {
constructor(){
super();
this.state = {
imageSource: []
}
}
componentDidMount(){
dbx.filesListFolder({path: ''})
.then((response) => {
let fileList = response.entries;
this.setState({
imageSource: fileList
});
})
}
render(){
if(!this.state.imageSource.length)
return null;
let images = this.state.imageSource.map((el, i) => (
<img key={i} className='images' src={el.path_lower} />
))
return (
<div className="folioWrapper">
{images}
</div>
);
}
}
You should be using your component's state or props so that it will re-render when data is updated. The call to Dropbox should be done outside of the render method or else you'll be hitting the API every time the component re-renders. Here's an example of what you could do.
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = {
imageSource: []
}
}
componentDidMount() {
dbx.filesListFolder({ path: '' }).then(function(response) {
const fileList = response.entries;
this.setState({
imageSource: fileList.map(file => file.path_lower);
})
});
}
render() {
return (
<div className="folioWrapper">
{this.state.imageSource.map((image, i) => <img key={i} className="images" src={image} />)}
</div>
);
}
}
If there are no images yet, it'll just render an empty div this way.
First off, you should be using the component's state and not using globally defined variables.
So to avoid showing the component with an empty array of images, you'll need to apply a conditional "loading" class on the component and remove it when the array is no longer empty.