Matho
Matho

Reputation: 125

React with Redux: returns incorrect state object

I have React with Redux and Electron project. I try to save current screen id to redux and get the saved state on next screen. The problem is, that when I use getSettings, the return value should be my saved state:

Object{settings: Object}

but is action's object:

Object{type: "GET_SETTINGS", payload: ""}

When I put console log to reducer_settings.js, it show correct state. So it seems it is something with binding the getSettings method. Thanks for your help

containers/screen_picker.js:

import React, {Component} from 'react';
import Navigation from "../components/navigation";
const {desktopCapturer, ipcRenderer} = require('electron');
import {connect} from 'react-redux';
const domify = require('domify')
import App from '../components/app'
import {bindActionCreators} from 'redux';
import {setSettings, getSettings} from "../actions/index";

class ScreenPicker extends App {
    constructor(){
        super();
        this.showPicker();
    }

    showPicker(){
        ipcRenderer.send('show-picker', { types: ['screen'] });

        ipcRenderer.on('get-sources', (event, options) => {
            desktopCapturer.getSources(options, (error, sources) => {
                if (error) throw error
                let sourcesList = document.querySelector('.capturer-list')
                for (let source of sources) {
                    let thumb = source.thumbnail.toDataURL()
                    if (!thumb) continue
                    let title = source.name.slice(0, 20)
                    let item = `<li><a href="#"><img src="${thumb}"><span>${title}</span></a></li>`
                    sourcesList.appendChild(domify(item))
                }
                let links = sourcesList.querySelectorAll('a')
                for (let i = 0; i < links.length; ++i) {
                    let closure = (i) => {
                        return (e) => {
                            e.preventDefault()
                            // ipcRenderer.send('source-id-selected', sources[i].id)
                            // sourcesList.innerHTML = ''

                            this.props.setSettings({
                               screenId: sources[i].id
                           });
                        }
                    }
                    links[i].onclick = closure(i)
                }
            })
        })
    }

    render() {
        return (
            <div className="window-wrapper">
                <div className="main-content">
                    <div className="capturer-container dn">
                        <div className="cr">
                            <p className="mbl">Select the window you want to share:</p>
                            <ul className="capturer-list"></ul>
                        </div>
                    </div>
                </div>
                <Navigation nextRouteUrl="/camera-test" backRouteUrl="/"  />
            </div>
        )
    }

}

function mapStateToProps(state){
    return {
        settings: state.settings
    }
}

function mapDispatchToProps(dispatch){
    return bindActionCreators({setSettings, getSettings}, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(ScreenPicker);

containers/camera_test.js

const {ipcRenderer} = require('electron');
import React, {Component} from 'react';
import Navigation from "../components/navigation";
import {connect} from 'react-redux';
import App from '../components/app'
import {bindActionCreators} from 'redux';
import {getSettings} from "../actions/index";

class CameraTest extends App {
    constructor(){
        super();
    }

    componentDidMount() {
        console.log("settings in camera test start");
        console.log(this.props.getSettings());
        console.log("settings in camera test end");
        ipcRenderer.send('stepWindow:create', { });
    }

    render() {
        return (
            <div className="window-wrapper">
                <div className="main-content">
                    CameraTest div
                </div>
                <Navigation nextRouteUrl="/camera-test" backRouteUrl="/screen-picker"  />
            </div>
        )
    }

}

function mapStateToProps(state){
    return {
        settings: state.settings
    }
}

function mapDispatchToProps(dispatch){
    return bindActionCreators({getSettings}, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(CameraTest);

reducers/reducer_settings.js:

import {GET_SETTINGS, SET_SETTINGS} from "../actions/index";

export default function (state = {},action) {
    let newState;

    switch (action.type){
        case GET_SETTINGS:
            console.log("reducer GET_SETTINGS");

            console.log(state);
            return state;
        case SET_SETTINGS:
            newState = { ...state, ["settings"]: action.payload };
            console.log("Start newstate");
            console.log(newState);
            console.log("End newstate");
            return newState;

        default:
            return state
    }
}

actions/index.js

export const SET_SETTINGS = 'SET_SETTINGS';
export const GET_SETTINGS = 'GET_SETTINGS';

export function setSettings(values, callback){
    return {
        type: SET_SETTINGS,
        payload: values
    }
}

export function getSettings(){
    console.log("actions#getSettings");

    return {
        type: GET_SETTINGS,
        payload: ""
    }
}

Upvotes: 1

Views: 1120

Answers (1)

Sujit.Warrier
Sujit.Warrier

Reputation: 2879

you dont need the getSetting action creator.

in your component did mount access the settings like this.

componentDidMount() {
    console.log("settings in camera test start");
     const { settings} = this.props;
    console.log(settings);
    console.log("settings in camera test end");
    ipcRenderer.send('stepWindow:create', { });
}

assuming your object is called settings. normally the object is given the name you are exporting in the reducer. so if you are not able to see an object called settings in props, you need to give your reducer function a name

export default function settings (state = {},action) {
let newState;

switch (action.type){
    case GET_SETTINGS:
        console.log("reducer GET_SETTINGS");

        console.log(state);
        return state;
    case SET_SETTINGS:
        newState = { ...state, ["settings"]: action.payload };
        console.log("Start newstate");
        console.log(newState);
        console.log("End newstate");
        return newState;

    default:
        return state
}
}

EDIT: its mapStateToProps which gives the object name is props.

Upvotes: 2

Related Questions