my function is:
getImage(page){
return
(
<Image
style={{position:'absolute',height:'60%',width:'90%',padding:50,bottom:30 ,alignSelf: 'center' }}
source={require('../../images/backgrounds/introduction/'+page.img)}
/>
)
}
render(){
return (
...
{this.getImage(activePage)}
)
}
but I got this error message:
Error: /Users/***/components/login/Introduction.js:85:14: calls to `require` expect exactly 1 string literal argument, but this was found: `require('../../images/backgrounds/introduction/' + page.img)`.
Instead of concatenation in require() you can use state.
Initialize one state say imageArray={page1:require('link of page 1 image'),page2:require('link of page 2 image')}
Then in getImage() use Image like this,
<Image
style={{position:'absolute',height:'60%',width:'90%',padding:50,bottom:30 ,alignSelf: 'center' }}
source={this.state.imageArray[page]}
/>
where page is the key from one of item of imageArray state.
Related
I have a route like this: <Route exact path="/product/:id" component={Product} /> inside a Switch. Inside the component Product I have a custom hook that makes a request to my api. I also have another component inside Product called: Configurator.
Inside the Configurator component I make another api request to get a specific choice. Then inside the render of the Configurator component I check which component I need to render.
{loading ? <Loading /> :
choices.map((choice, index) => {
return (
<div
key={choice.id}
id={choice?.id}
ref={choice?.id == activeChoice ? myRef : empty}
className={`${choice?.id == activeChoice ? "active" : "inactive"} configurator__choice`}
onClick={() => enableChoice(choice?.id)}
>
{choice?.type === "parent_size" ? <ChoiceSize key={choice.id} number={index + 1} choiceData={choice} availableChoices={availableChoices} activeChoice={activeChoice} onChange={onChange} choices={choices} fetchNewChoiceData={fetchNewChoiceData} onSubmit={onSubmit} /> : <div></div>}
{choice?.type === "parent" ? <ChoiceOption key={choice.id} number={index + 1} choiceData={choice} availableChoices={availableChoices} activeChoice={activeChoice} choiceNameId={choice?.id} choiceId={choice?.choices[0]?.next.id} onClick={onClick} /> : <div></div>}
</div>
)
})
}
So when choice.type is equal to parent_size it loads the ChoiceSize component and adds data as props.
The problem I have is that whenever I am for example on /product/1 and I want to switch to /product/2 my old components (ChoiceSize and/or ChoiceOption) won't go away. It will add new choices with the data from product 2 but the old choices from product 1 are still there.
Does anyone know how I can fix this? Maybe that the whole component gets unmounted and the old choices will get removed and the new choices will get added
I have created a component and it's running well in local server. But I am getting below warning
Warning: Each child in a list should have a unique "key" prop.
Getting this warning means we need to fix the key index props? as given here.
below is some snippets of my component code..
render() {
return (
<div>
<Container>
<Row>
<Col className="col-12">
{this.state.client.map((val,index)=>{
if(index == this.state.colaborators.length -1)
return <a href={"/users/"+val}>{val}</a>
return <a href={"/users/"+val}>{val} ,</a>
})}
</Col>
</Row>
</Container>
</div>
</div>
</div >
);
}
}
export default App;
I checked some solution from here
As I told my code is working well. Can we use some fake key props? for example
key={fake index}
And we are using will this affect in my working code?
If this.state.client ever changes, don't just use the index (which is sadly common); see this article for why and its demo of what can go wrong. You can only do that with a list that never changes, or only grows/shrinks (and not at the same time), not with one where the order changes (you insert at the beginning, or sort, or...) More in the docs.
I'm guessing val will be unique in the list, so use that as the key:
{this.state.client.map((val, index) => {
const href = "/users/" + val;
const display = index == this.state.colaborators.length - 1 ? val : `${val} ,`;
return <a key={val} href={href} >{display}</a>;
})}
If your lists order is not going to change, simply use:
return <a key={index} href={"/users/"+val}>{val}</a>
return <a key={index} href={"/users/"+val}>{val} ,</a>
It will not affect your code and it will remove the warning.
I have the following < CardHeader /> component inside a < Card />.
<CardHeader
title={card.title}
subheader={`${moment(card.createdAt).startOf('minute').fromNow()}` + ' by ' + <div>ABC</div>}/>
It renders the following way:
18 minutes ago by [object Object].
What is the right way of doing this? Thanks in advance!
You can pass on a node to CardHeader's subHeader props, just don't mix string and html
<CardHeader
title={card.title}
subheader={<div>{moment(card.createdAt).startOf('minute').fromNow()} by ABC</div>}/>
Sample DEMO
Wrap your heading in a fragment
You can separate out part of your logic to its own level. This will make reuse easier, and testing also easier.
const MyHeading = ({card}) => {
return (
<React.Fragment>
{`${moment(card.createdAt).startOf('minute').fromNow()} by`
<div>ABC</div>
</React.Fragment>
)
}
In the above I'm only retrieving card, but you can pass all sorts of data to your heading component.
<CardHeader
title={card.title}
subheader={<MyHeading {...props} />
/>
I have a list of objects photos, from a json data file, that I would like to organize into 3 different <div> columns, but I dont know how to achieve that, here is my broken non-optimized code:
<div className="container">
<div ref={leftColRef} className="left-col" />
<div ref={centreColRef} className="centre-col" />
<div ref={rightColRef} className="right-col" />
{Object.keys(photos).forEach((n, i) => {
const id = photos[n].id;
const thumb = photos[n].thumbnailUrl;
const title = photos[n].title;
const element = (
<Thumbnail id={id} title={title} thumb={thumb} />
);
if (i % 3 === 0) {
leftColRef.current.append(element);
} else if (i % 3 === 1) {
centreColRef.current.append(element);
} else {
rightColRef.current.append(element);
}
// this line works, it idsplays the data but is commented as the data needs to go inside its respective columns
// return <Thumbnail key={id} title={title} thumb={thumb} />;
})}
</div>
The idea is to insert some elements into the left-column when i%3 = 0 and others in the centre-column when i%3 = 1 and so on ...
And a link to my codesandbox
Any help/advise will be much appreciated.
Easiest is probably to prepare the data outside the render function and to render the column one by one.
You should not manipulate the DOM like it's done in jQuery using JSX
Example:
const Component = (props) => {
const filterPhotos = (column) => {
return props.photos.filter((photo,index)=> index%3==column);
}
return <>
<MyColumn photos={filterPhotos(0)}/>
<MyColumn photos={filterPhotos(1)}/>
<MyColumn photos={filterPhotos(2)}/>
</>;
}
First, using ref on div to inject stuff on it is wrong. It's the opposite of how react works.
Like charlies said, I would split the photos in 3 different arrays before the render. Then, you'll be able to do something like this :
<div ref={leftColRef} className="left-col" />
{ photosLeft.map(photo => <Thumbnail key={photo.id} {...photo} />)
</div>
when preparing your data, try to use the same object properties and component props name so you can spread it easily ( {...photo} ).
Note: Also, when rendering an array in react, each child must have a unique key props. It will help react to render on that part of dom if your data change.
I am trying to use the above code, but I am getting an error during the build process saying this.selectTable is null.
Can anybody help me out with this?
I have followed this logic - Access filtered data in ReactTable
<ReactTableComponent
ref={this.reactTable}
className="polls-table"
defaultPageSize={10}
getTrProps={(_, rowInfo = {}) => {
let { index = 0 } = rowInfo;
return {
style: {
background: index % 2 ? "#fafafa" : "#FFFFFF"
}
};
}}
columns={columns}
data={polls}
/>
<Button
color="primary"
type="button"
onClick={download(this.reactTable.current.getResolvedState())}
>
Download
{/* <CSVLink data={myFunction(this.selectTable.getResolvedState())} filename="polls.csv">Export to CSV</CSVLink> */}
</Button>
</Paper>;
A problem is within this line:
onClick={download(this.reactTable.current.getResolvedState())}
What happens now is the JS running your code right away to calculate the onClick handler. And just because the ref on the first run is null, the error occurs.
What you should have instead is this:
onClick={() => {download(this.reactTable.current.getResolvedState())}}
You can also add condition to check wheter this.reactTable.current is not null