I am working on a show page based on the match.params
from react router 4. For some reason, some functions runs 3 times which gives me the first 2 times undefined and the third time the result I want.
So I have this Show component which have the props "projects" from the main component. In this show component I do a find function on the array with the props projects inside of it. This must return a 1 item with the project.id
equel to match.params.id
. This is going good, and If I visit the page by clicking on a button (through the application) I get the page with the right project and properties (e.g. project.name
). But If I do a reload or visit the page by using an url in the browser, I get an error saying property name is undefined. If I look in the console I see that my console.logs are fired 3 times. Like I said, the first 2 are undefined and the third is giving me the result I want. I guess the first 2 are resulting in the error I get.
My Show component
import React from 'react'
import { Button } from 'reactstrap'
const Show = ({match, projects}) => {
let project = projects.find((project) => {
//Return project with the id equel to the match.params.id
return project.id == match.params.id;
});
//Both these console.logs runs 3 times when visiting a link by url
console.log(project); //this one gives me 2 times undefined, third time is the right item
console.log(match.params.id)
return(
<div className="container p-40">
<div className="projects-header">
{/* If I echo project.name it will gives me 'cannot read property 'name' of undefined' */}
<h2>Project '{match.params.id}' {/* {project.name} */}</h2>
<Button className="btn btn-primary" onClick={() => console.log('save')}>Save</Button>
</div>
<div className="project-edit">
</div>
</div>
);
};
export default Show;
The route in the parent component
<Route exact path="/projects/show/:id" render={(props) => <Show {...props} projects={this.state.projects} />} />
Someone with a good solution for this problem? I find it a problem that my users can't route by the url. I don't know why my show component fires 3 times either by url/reload.
Edit (Added parent component):
//Import react
import React, { Component } from 'react';
//Import custom components
import Sidebar from './components/js/Sidebar'
import Dashboard from './components/js/Dashboard'
import Projects from './components/js/Projects'
import Show from './components/js/projects/Show'
//Import styles
import './App.css';
//3rd party deps
import { BrowserRouter as Router, Route } from "react-router-dom";
import axios from 'axios'
class App extends Component {
constructor() {
super();
this.state = {
//Times / Time tracking
times: [],
timer: false,
currentTimer: 0,
//Current task
currentTask: {
id: 3,
title: '',
project_id: {
id: '',
name: '',
color: ''
},
date: '',
time_total: ''
},
//Projects
projects: []
}
this.addTask = this.addTask.bind(this);
this.startTimer = this.startTimer.bind(this);
this.stopTimer = this.stopTimer.bind(this);
this.addProject = this.addProject.bind(this);
}
addTask = (task) => {
let newArray = this.state.times.slice();
newArray.push(task);
this.setState({times: newArray, currentTimer: 0, timer: false});
clearInterval(this.timerID);
}
addProject = (project) => {
let newArray = this.state.projects.slice();
newArray.push(project);
this.setState({ projects: newArray });
}
startTimer() {
let sec = this.state.currentTimer;
const start = Date.now();
this.setState({ timer: true });
this.timerID = setInterval(() => {
let time = new Date() - (start - sec * 1000);
this.setState({ currentTimer: Math.round(time / 1000)});
}, 1000);
}
stopTimer() {
this.setState({ timer: false });
console.log('stopped');
clearInterval(this.timerID);
//Clear interval here
}
componentDidMount() {
// Make a request for a user with a given ID
axios.get('/Sample.json')
.then((response) => {
this.setState({times: response.data});
});
axios.get('/Projects.json')
.then((response) => {
this.setState({projects: response.data});
});
}
render() {
return (
<Router>
<div className="page-wrapper">
<Sidebar />
<Route exact path="/" render={() => <Dashboard times={this.state.times} timer={this.state.timer} startTimer={this.startTimer} stopTimer={this.stopTimer} currentTimer={this.state.currentTimer} addTask={this.addTask} />} />
<Route exact path="/projects" render={() => <Projects projects={this.state.projects} addProject={this.addProject} />} />
<Route exact path="/projects/show/:id" render={(props) => <Show {...props} projects={this.state.projects} />} />
</div>
</Router>
);
}
}
export default App;