S
S
s243442019-06-29 13:05:39
React
s24344, 2019-06-29 13:05:39

How to properly pass props to React?

Hello. I deal with a small problem on React.js. In the TimerComponent I have a handleStart method. It already describes the mechanics of changing the state in the setTimeout function.
But I:

this.props {
   currentInterval: undefined
}

I'm not strong in React, tell me where this props got lost?
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';


const createStore = (reducer, initialState) => {
    let currentState = initialState;
    const listeners = [];

    const getState = () => currentState;

    const dispatch = action => {
        currentState = reducer(currentState, action);
        listeners.forEach(listener => listener())
    }

    const subscribe = listener => listeners.push(listener);

    return {getState, dispatch, subscribe}
}

const connect = (mapStateToProps, mapDispatchToProps) =>
    Component => {
        class WrappedComponent extends React.Component {
            render() {
                return (
                    <Component
                        {...this.props}
                        {...mapStateToProps(this.context.store.getState(), this.props)}
                        {...mapDispatchToProps(this.context.store.dispatch, this.props)}
                    />
                )
            }

            componentDidUpdate() {
                console.log('componentDidUpdate');
                this.context.store.subscribe(this.handleChange)
            }

            handleChange = () => {
                console.log('handleChange');
                this.forceUpdate()
            }
        }

        WrappedComponent.contextTypes = {
            store: PropTypes.object,
        }

        return WrappedComponent
    }

class Provider extends React.Component {
    getChildContext() {
        return {
            store: this.props.store,
        }
    }

    render() {
        return React.Children.only(this.props.children)
    }
}

Provider.childContextTypes = {
    store: PropTypes.object,
}

// APP

// actions
const CHANGE_INTERVAL = 'CHANGE_INTERVAL'

// action creators
const changeInterval = value => ({
    type: CHANGE_INTERVAL,
    payload: value,
})

// reducers
const reducer = (state, action) => {
    switch (action.type) {
        case CHANGE_INTERVAL:
            return state += action.payload

        default:
            return {}
    }
}

// components

class IntervalComponent extends React.Component {
    render() {

        console.log('class IntervalComponent this.state', this.state);
        console.log('class IntervalComponent this.props', this.props);

        return (
            <div>
                <span>Интервал обновления секундомера: {this.props.currentInterval} сек.</span>
                <span>
                  <button onClick={() => this.props.changeInterval(-1)}>-</button>
                  <button onClick={() => this.props.changeInterval(1)}>+</button>
                </span>
            </div>
        )
    }
}

const Interval = connect(dispatch => ({
        changeInterval: value => dispatch(changeInterval(value)),
    }),
    state => ({
        currentInterval: state,
    }))(IntervalComponent)

class TimerComponent extends React.Component {
    state = {
        currentTime: 0
    }

    handleStart = () => {

        console.log('this.state', this.state);
        console.log('this.props', this.props);

        setTimeout(() => this.setState({
            currentTime: this.state.currentTime + this.props.currentInterval,
        }), this.props.currentInterval)
    }

    handleStop = () => {
        console.log(this);
        this.setState({currentTime: 0})
    }

    render() {

        console.log('this.props', this.props);

        return (
            <div>
                <Interval/>
                <div>
                    Секундомер: {this.state.currentTime} сек.
                </div>
                <div>
                    <button onClick={this.handleStart}>Старт</button>
                    <button onClick={this.handleStop}>Стоп</button>
                </div>
            </div>
        )
    }
}

const Timer = connect(state => ({
    currentInterval: state,
}), () => {
})(TimerComponent)

// init
ReactDOM.render(
    <Provider store={createStore(reducer)}>
        <Timer />
    </Provider>,
    document.getElementById('app')
)

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Spirin, 2019-06-29
@rockon404


...Understood with a small problem on React.js.
...I'm not strong in React.
Well, that's not how it's done.
I don't know whose code you used, but to use the context, you no longer need to use PropTypes.
Don't pass initialState.
In the connect call, you pass mapDispatchToProps first, then mapStateToProps in places.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question