Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/components/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default class Main extends React.Component {
</div>
<Switch>
<Route exact path="/" component={StudentList} />
<Route exact path='/student/:id' component={SingleStudent} />
</Switch>
</Router>
);
Expand Down
30 changes: 29 additions & 1 deletion client/components/SingleStudent.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import React from 'react';
import { Route, Link } from 'react-router-dom'
import { connect } from 'react-redux';
import { getSingleStudent, fetchSingleStudent } from "../redux/store";

const avgGrade = (tests) => {
return Math.round(
Expand All @@ -11,6 +14,18 @@ class SingleStudent extends React.Component {
super(props);
}


componentDidMount () {
try {
const studentId = this.props.match.params.id
this.props.getSingleStudent(id)
}
catch (error) {
console.error(error)
}
}


render() {
const { student } = this.props;
const hasTests = student.tests.length;
Expand Down Expand Up @@ -50,4 +65,17 @@ class SingleStudent extends React.Component {
}
};

export default SingleStudent;
const mapStateToProps = (state) => {
return {
student: state.singleS
}
}

const mapDispatchToProps = (dispatch) => {
return {
getSingleStudent: (id) => dispatch(fetchSingleStudent(id))
}
}


export default connect(mapStateToProps, mapDispatchToProps)(SingleStudent)
78 changes: 59 additions & 19 deletions client/components/StudentList.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,49 @@
import React from 'react';
import {Link} from 'react-router-dom'
import { connect } from 'react-redux'
import {fetchStudents} from '../redux/store'
// thunk is imported because it's middle ware

const DUMMY_DATA = [
{
id: 1,
fullName: "Jordan Walke",
firstName: "Jordan",
lastName: "Walke",
email: "jw@react.com",
},
{
id: 2,
fullName: "Dan Abramov",
firstName: "Dan",
lastName: "Avramov",
email: "da@react.com",
}
]
// const DUMMY_DATA = [
// {
// id: 1,
// fullName: "Jordan Walke",
// firstName: "Jordan",
// lastName: "Walke",
// email: "jw@react.com",
// },
// {
// id: 2,
// fullName: "Dan Abramov",
// firstName: "Dan",
// lastName: "Avramov",
// email: "da@react.com",
// }
// ]

class StudentList extends React.Component {
constructor(props) {
super(props);
}

componentDidMount() {
this.props.loadStudents()
}

render() {
console.log('RENDER SOMETHING ')
// going to mapStateToProvps via pops and mapping throught he stu
return (
<ul>
{DUMMY_DATA.map((student) => (
<ul>
{/* this was DUMMY_DATA BUT WE GET THE STATE FROM THE PROPS ON didMount*/}
{this.props.students.map((student) => (
<li key={student.id}>
<div>
<p>Name: {student.fullName}</p>
<p>Email: {student.email}</p>
<div>
<Link to={`/student/${student.id}`}> View Detail </Link>
</div>
</div>
</li>
))}
Expand All @@ -40,4 +53,31 @@ class StudentList extends React.Component {
}
}

export default StudentList;
// Mapping the inital state array from the store to this componenet
// we only need students - so state.students is going to STORE and giving us the initialState ={ students: [] }
const mapStateToProps = (state) => {
console.log('MAP STATE TO PROPS')
return {
students: state.students
}
}

// This is mapping the to the THUNK creator that we need to dispatch the action to update the state in the reducer
//
function mapDispatchToProps(dispatch) {
console.log('MAPDISPATCH TO PROPS')
return {// This is a reference to store.dispatch
loadStudents: () => {dispatch(fetchStudents())}// Wrapper function that dispatches the action
}
}
// you can name loadStudents anything : you are just naming this function
// this only exists in this component
// you are dispatching the THUNK and since the thunk took no parameters you give none here.

// if you have a component that doesn't take state then you don't need state.

export default connect(mapStateToProps, mapDispatchToProps)(StudentList)
// connect is just something from React Redux
// it just gives them both access


71 changes: 56 additions & 15 deletions client/redux/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,80 @@ import axios from 'axios';
import thunkMiddleware from 'redux-thunk';

// ACTION TYPES go here:
const GOT_STUDENTS = 'GOT_STUDENTS';

const GET_STUDENTS = 'GET_STUDENTS'
const GET_SINGLE_STUDENT = 'GET_SINGLE_STUDENT'

// ACTION CREATORS go here:
const gotStudents = (students) => ({
type: GOT_STUDENTS,
students
});

export const getStudents = (students) => {
return {
type: GET_STUDENTS,
students
}
};

// THUNK CREATORS go here:
const fetchStudents = () => async (dispatch) => {
const {data} = await axios.get('/api/students');
dispatch(gotStudents(data));

export const getSingleStudent = (id) => {
return {
type: GET_SINGLE_STUDENT,
student
}
}


// THUNK CREATORS go here:

// Student List THUNK
// If you are doing a getAll() call - then you don't need to put any params

export const fetchStudents = () => {
return async (dispatch) => {
try {
const {data} = await axios.get('/api/students')
dispatch(getStudents(data))
} catch(err) {
console.log(err)
}
}
};

// Single Student THUNK
export const fetchSingleStudent = (id) => {
return async (dispatch) => {
try {
const {data} = await axios.get(`/api/students/${id}`)
dispatch(getSingleStudent(data))
} catch (err) {
console.log(err)
}
}
};


//_________________________________________________
const initialState = {
students: []
students: [] // you missed this !! itemize initialState
};

const reducer = (state = initialState, action) => {
switch(action.type) {
case GOT_STUDENTS:
return {
students: action.students
}
case GET_STUDENTS:
return {
students: action.students
} //students must match within the Action Creator
// This is just replacing the empty intial state [] with a new array gotten from the action creator & the thunk
case GET_SINGLE_STUDENT:
return action.student
default:
return state;
}
}
};

const store = createStore(reducer, applyMiddleware(thunkMiddleware, loggerMiddleware));

// dispatch your own actions here to test your store functionality:
store.dispatch({type: 'HELLO_WORLD'})
// ^ you can see the logs above in your console, thanks to redux-logger!

export default store;