Michal
Michal

Reputation: 5220

React / Redux passing props to main component

I am still quite confused about data flow in React / Redux build. I am fairly comfortable when working "in" my app but I can't figure out how to pass data to my app from server?

I have react-app.php file with article#main-content element which is base element for my app. I want to pass the element information about some product.

How do I do that?

I wanted to give article#main-content prop productName but I don't know how to access it from react.

My guess is from reducer ... but how? Maybe I should not relly on article#main-content and pass variables to react in $_GET parameters?

react-app.php

<link rel="stylesheet" type="text/css" href="/lines-configurator/build/style.css" media="screen"/>
<script async type="text/javascript" src="/lines-configurator/build/bundle.js"></script>

<article id="main-content" productName="My Product">
</article>

App.js:

import React from 'react';
import {render} from 'react-dom';
import {createStore} from 'redux';
import {Provider} from 'react-redux';
import reducer from './reducers/index';

import BoardConfig from './containers/BoardConfigContainer';
import BoardProduct from './containers/BoardProductContainer';

const store = createStore(reducer, window.devToolsExtension && window.devToolsExtension());

render(
    <Provider store={store}>
        <div>
            <BoardConfig />
            <BoardProduct />
        </div>
    </Provider>,
    document.getElementById('main-content')
);

BoardProductContainer.js

import {connect} from 'react-redux';
import BoardProduct from '../components/BoardProductComponent';

export default connect(
    function mapStateToProps(state) {
        return {

        };
    },
    function mapDispatchToProps(dispatch) {
        return {};
    }
)(BoardProduct);

BoardProductComponent.js

import React from 'react';

export default function () {
    return ();
}

BoardProductReducer.js

import * as types from '../constants/constants';
import Immutable from 'immutable';

const initialState = Immutable.Map({});

export default function boardReducer(state = initialState, action) {
    switch (action.type) {
        default:
            return state;
    }
}

Upvotes: 0

Views: 1302

Answers (3)

NULL pointer
NULL pointer

Reputation: 1377

I do this differently. I define global javaScript variables in the html head when I am rendering my page in php - I am using a blade template, so mine looks like this:

var orgUnitIdGlobal = {!! json_encode($orgUnitId, JSON_FORCE_OBJECT) !!};

Then in my app.js I can call on that variable:

var elementId = 'appRoot';
if (document.getElementById(elementId)) {
	let store = createStore(reducer,{
		orgUnitId : orgUnitIdGlobal
	});
	ReactDOM.render(
		<Provider store={store}>
			<MyComponent />
		</Provider>,
		document.getElementById(elementId)
	)
}

the 'orgUnitId' is then passed through to my reducer:

import orgUnitId from './orgUnitId.js'
...other reducers for other parts of the state...
export default combineReducers({
    orgUnitId,
...other reducers....
})

and as i pass {orgUnitId: orgUnitIdGlobal} as the second parameter to my createStore, it is passed through as the state in the call to the orgUnitId(state,action) when the component is being initialised.

I can then refer to that value (I think) from other reducers, and make what ever API calls I need - like api.com/getname?orgUnitId=7 in the getName reducer.....

Upvotes: 1

BrunoLM
BrunoLM

Reputation: 100331

You can get url parameters from

this.props.location.query

Ex:

// http://localhost:3000/?test=1

console.log(this.props.location.query);
/*
{
  test: "1"
}
*/

Passing server vars other than $_GET

Normally you would call and action that makes an ajax request and return in the reducer.

But since you already have a value since the beginning what you can do is wrap the code of your App.js in a start function

export default function start(serverVar) {
    // use serverVar here:
    const store = createStore(reducer, window.devToolsExtension && window.devToolsExtension());

    render(
        <Provider store={store}>
            <div>
                <BoardConfig />
                <BoardProduct />
            </div>
        </Provider>,
        document.getElementById('main-content')
    );
}

Change your webpack's output to include:

library: 'Foo'

On your html file add:

<script type="text/javascript">
  Foo.start('<?php echo $serverVar; ?>');
</script>

Or simply

Ignore all the setup above and just do this

<script type="text/javascript">
  window.someValue = '<?php echo $serverVar; ?>';
</script>

Upvotes: 2

Radu Szasz
Radu Szasz

Reputation: 1021

I would normally create an action, with the following flow:

  • Dispatch event { type: GETTING_DATA, status: IN_PROGRESS }. Now based on this, the reducer could modify the state such that you can display a spinner or whatever element you prefer, to let the user know data is loading.

  • Perform AJAX request to the server and get the data.

  • a) Dispatch event { type: GETTING_DATA, status: SUCCESS } if the data was retrieved successfully. The reducer can now update the state and your component will re-render.

  • b) Dispatch event { type: GETTING_DATA, status: FAILED } if there was a problem while retrieving data. The reducer can now modify the state in such a way that the user knows some error occurred.

Hope that helps!

Upvotes: 1

Related Questions