Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't Set Checkbox State With setState by Reading from User Preference #128

Open
HyperGrapher opened this issue Sep 17, 2018 · 1 comment

Comments

@HyperGrapher
Copy link

There are two check boxes. I want to set defaultChecked value to values coming from ipcMain (saved user preference) but even the state is true, it's always in unchecked position. Checked the state in render function, it logs true but I can't set them.

I am reading from the default values saved in json (with electron-settings package) There are two of them one is true one is false. No matter what I tried Checkboxes always false.

I have no experience in react, so if it is a silly mistake, I'm sorry:)

Here is my code:
Also full github repository is here:
(https://github.com/hullabaloon/react-desktop-checkbox)

import React from "react";
import { Checkbox } from "react-desktop/macOs";

import { IPC_READ_ALL_PREFS, IPC_GET_ALL_PREFS } from "./constants";
const electron = window.require("electron");
const ipcRenderer = electron.ipcRenderer;
export default class PreferencesPage extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isCheckedTerminal: false,
      isCheckedHistory: false
    };
    
    this.ipcGetAllPrefs = this.ipcGetAllPrefs.bind(this);

    this.toggleChangeTerminal = this.toggleChangeTerminal.bind(this);
    this.toggleChangeHistory = this.toggleChangeHistory.bind(this);

    
  }

  // Prevent Memory Leak by removing listeners..
  componentWillUnmount() {
    ipcRenderer.removeListener(IPC_GET_ALL_PREFS, this.ipcGetAllPrefs);
  }

  componentWillMount() {}

  // Send IPC command to read preferences
  componentDidMount() {

    ipcRenderer.on(IPC_GET_ALL_PREFS, this.ipcGetAllPrefs);

    ipcRenderer.send(IPC_READ_ALL_PREFS, "ping");

    console.log("Component DID Mount - TERMINAL: ", this.state.isCheckedTerminal); // true
    console.log("Component DID Mount - HISTORY: ", this.state.isCheckedHistory); // false
  }

  // ## IPC METHOD ## //
  ipcGetAllPrefs(event, allPrefs) {
    console.log("ipcGetAll TERMINAL: ", allPrefs.pref_terminal.value); // true
    console.log("ipcGetAll HISTORY: ", allPrefs.pref_history.value); // false

    // Set state with saved user preference coming from main
    // Saving data not implemented yet. Reads from default values. 
    this.setState({
      isCheckedTerminal: allPrefs.pref_terminal.value, // true
      isCheckedHistory: allPrefs.pref_history.value //  false
    });
  }

  // ##  Toggle  ##

  toggleChangeTerminal = () => {
    this.setState({
      isCheckedTerminal: !this.state.isCheckedTerminal
    });
  };
  toggleChangeHistory = () => {
    this.setState({
      isCheckedHistory: !this.state.isCheckedHistory
    });
  };

  render() {
    console.log("CALLED FROM RENDER: ", JSON.stringify(this.state)); // obj1:true and and obj2: false

    return (
      <div>
        <Checkbox
          label="Terminal"
          onChange={this.toggleChangeTerminal}
          defaultChecked={this.state.isCheckedTerminal}
        />

        <Checkbox
          label="History"
          onChange={this.toggleChangeHistory}
          defaultChecked={this.state.isCheckedHistory}
        />
      </div>
    );
  }
}


@AndrewKralovec
Copy link

AndrewKralovec commented Feb 23, 2019

Yeah,
I see that defaultChecked is passed in as a prop, but then it is read into checked in the Checkbox state.
So that value is really just for initialization.

constructor(props) {
  super();
  this.state = {
    checked: !!props.defaultChecked === true,
    transition: true
  };
}
....
onChange = evet => {
  this.setState({ checked: event.target.checked });
  if (this.props.onChange) {
    this.props.onChange(event);
  }
};
....
<Checkmark
  show={this.state.checked}
  color={checkMarkColor}
  shadowColor={shadowColor} />

@gabrielbull , to resolve this, what if we created a CheckBoxBase component. This component would be a styled-component with the current UI/styling as CheckBox, but having all the logic moved to props, so that the user can extent the CheckBox as they see fit.

In this case, the user could have used the CheckBoxBase component, and passed the parent state values ( isCheckedTerminal, isCheckedHistory), as props so that the values are bound to the parent state, instead of the child state. The parent state can then be updated , and those values would then trigger the desired logic.

ex:

const CheckBox = styled.input.attrs({ type: checkbox })`
  WebkitUserSelect: none;
  userSelect: none;
  WebkitAppearance: none;
  appearance: none;
  borderWidth: 1px;
  borderStyle: solid;
  borderColor: #b8b8b8;
  borderRadius: 3px;
  backgroundColor: #ffffff;
  padding: 6px;
  margin: 0 1px;
  boxShadow: inset 0 1px 0 0 rgba(224; 224; 224; .4);
  transition: all 0.4s;

  :focus {
    outline: none;
  }
...
`
 <CheckBox checked={checked} ...>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants