Case 3: Share business logic behind different rendering

// ./app/components/Profile/containers.js
import { goToClub, goToSubject } from '../actions';
import { getProfileById, getMyProfile } from './selectors';

const mapDispatchToProps = (dispatch, props) => {
    goToClub: bind(goToClub, dispatch),
    goToSubject: bind(goToSubject, dispatch)
}

/* 
export const translateAndConnect = (component) => 
    translate('AcccountViewer')(
        connect(mapDispatchToProps)(component))
*/

export const translateAndConnect = compose(
    translate('AcccountViewer'),
    connect(mapDispatchToProps))

const mapStateToProps = (state, props) => {
    let profile = getProfileById(state, props)
    return { ...profile }
}

// Design for open profile under specific schema
export const connectByProfileId = connect(mapStateToProps)

const mapMeToProps = (state, props) => {
    let me = getMyProfile(state);
    return { ...me }
}

// Design for MyProfile, MySetting, MyBookmarks pages
export const connectToMe = connect(mapMeToProps);
// ./app/components/Profile/_ProfileLayout.js
import { translateAndConnect as enhance } from './containers';

const Presenter = ({name, age, clazz, children}) => (
    <div>
        <span class="name">{name}</span>
        <span class="age">{age}</span>
        <span class="clazz">{clazz}</span>
        {...children}
    </div>
)

export default enhance(Presenter);
// ./app/components/Profile/StudentProfile.js

import { connectByProfileId } from './containers';

import ProfileLayout from './_ProfileLayout';

const Presenter = ({clubs_joined, t, goToClub}) => (
    <ProfileLayout>
        {clubs_joined && clubs_joined.map((club) =>
            <Link onClick={() => goToClub(club)}>
                <span>{t('JOIN_A_CLUB', club)}</span>
            </Link>
        )}
    </ProfileLayout>
)

// Pure rendering-oriented component prepared for further enhancement
export const ProvidedStudentProfile = Presenter;

export default connectByProfileId(Presenter);
// ./app/components/Profile/TeacherProfile.js
import { connectByProfileId } from './containers';

import ProfileLayout from './_ProfileLayout';

const Presenter = ({subjects_taught, t}) => (
    <ProfileLayout>
        {subjects_taught && subjects_taught.map((subject) =>
            <span>{t('TEACH_A_SUBJECT', subject)}</span>
        )}
    </ProfileLayout>
)

// Pure rendering-oriented component prepared for further enhancement
export const ProvidedTeacherProfile = Presenter;

export default connectByProfileId(Presenter);
// ./app/components/Profile/AutodetectedProfile.js

import { ProvidedTeacherProfile } from './TeacherProfile';
import { ProvidedStudentProfile } from './StudentProfile';
import { connectToMe } from './containers';

const Presenter = ({job_title, ...props}) => {
    switch (job_title) {
        case 'teacher';
            return <ProvidedTeacherProfile {...props}/>;
        case 'student':
            return <ProvidedStudentProfile {...props}/>;
        default: 
            return <div>{props.t('UNKNOWN_JOB_TITLE')}</div>
    }
}

export default connectToMe(Presenter);
// ./app/components/Profile/index.js

export TeacherProfile from './TeacherProfile';
export StudentProfile from './StudentProfile';
export MyProfile from './AutodetectedProfile';
// ./app/routes/index.js

import { StudentProfile, TeacherProfile, MyProfile } from '../components/Profile';

const RootRouter = () => (
    <Router>
        <Route path='/me' component={MyProfile}/>
        <Route path='/teacher/:profile_id' component={TeacherProfile}/>
        <Route path='/student/:profile_id' component={StudentProfile}/>
    </Router>
)

results matching ""

    No results matching ""