0

I'm new to React (16.4.2), and I'm trying to understand the way it works. I don't want to complicate things with redux; I just want to know about the core react library.

I have an application, and (eventually down the children chain) there is an input, which is a component, RangeInput. It's just a wrapper component for an input.

The problem is two parts

  1. I should be able to change the value within the range (as a user)
  2. if there is data in the local storage, it should load it the first time. This also means that the user should still be able to alter/change the input value.

Right now with this, I see to only be able to do one of the other. I know I'm not understanding something here.

What needs to happen?

Thanks, Kelly

Here are the classes:

export class RangeInput extends React.Component {
    constructor(props) {
       super(props);
       this.ds = new DataStore();
       this.state = {
          value: props.value
       };
    }

    static getDerivedStateFromProps(props, state) {
        console.log('props', props, 'state', state);
        if (props.value !== state.value) {
          return {value: props.value};
        }

        return null;
    }

    onChange(event) {
      const target = event.target;

      this.setState({
        value: target.value
      });

      if (this.props.onChange) {
        this.props.onChange({value: target.value});
      }
   }

   onKeyUp(event) {
      if (event.keyCode !== 9) {
        return;
      }

      const target = event.target;

      if (this.props.onChange) {
        this.props.onChange({value: target.value});
      }
  }

  render() {
       return <div>
           <input type="number" value={this.state.value}
           onChange={this.onChange.bind(this)}
           onKeyUp={this.onKeyUp.bind(this)}/>
       </div>;
    }
}

const DATA_LOAD = 'load';
export class Application extends React.Component {
    constructor() {
       super();

       this.state = {
          value: -1,
          load = DATA_LOAD
       };
    }

    componentDidMount() {
      if (this.state.load === DATA_LOAD) {
         this.state.load = DATA_CLEAN;
         const eco = this.ds.getObject('the-app');
         if (eco) {
            this.setState({value: eco});
         }
       }
    }

    render(){
       return <RangeInput value={this.state.value} />;
    }
}


ReactDOM.render(
  <Application/>,
  document.getElementById('root')
);
KellyTheDev
  • 891
  • 2
  • 12
  • 31
  • 2
    A lot of code seems to be missing, can you complete or make a sandbox? – remix23 Sep 10 '18 at 01:11
  • What do you mean by within the range? What is the value you are passing as a prop to RangeInput and why? And one more thing never do binding directly in render instead do it in constructor – Hemadri Dasari Sep 10 '18 at 01:19
  • There are obviously more properties that get sent to this component, `RangeInput`, but at the core this is the setup and `value` is the issue. The only thing to add is that with the `Application` there is a save to local storage, but that's only when `submit` is actually clicked, which means there is no "smart-save" feature – KellyTheDev Sep 10 '18 at 01:26

1 Answers1

0

I think this situation can be simplified quite a bit:

import React from 'react';

export const RangeInput = props => (
  <input
    value={props.value}
    onChange={props.setValue} />
)

export class Application extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: -1, };
  }

  componentDidMount() {
    var val = localStorage.getItem('myVal');
    if (val) this.setState({value: val})
  }

  setValue(e) {
    this.setState({value: e.target.value})
    localStorage.setItem('myVal', e.target.value);
  }

  render() {
    return <RangeInput
      value={this.state.value}
      setValue={this.setValue.bind(this)} />;
  }
}

Here we have two components: <RangeInput>, a stateless component, and <Application>, the brains behind the operation.

<Application> keeps track of the state, and passes a callback function to RangeInput. Then, on keydown, <RangeInput> passes the event object to that callback function. Application then uses the event object to update the state and the localStorage. On refresh, the last saved value is fetched from localStorage and present in the input (if available).

duhaime
  • 25,611
  • 17
  • 169
  • 224
  • 1
    thank you! I had a feeling something wasn't clicking for me. Simply put, when you described that the `application` was the brain of it all (which is what I was trying for), it made sense to me; meaning that I had it doing it partially, while you made it do it for its-full-on-glory. I was trying to have the Component manage its own psuedo simple state. In reality, that was the problem. The application should have been managing it all (as you have shown). Again, thanks for taking the time to show me the flow, it has helped me tremendously! – KellyTheDev Sep 10 '18 at 17:33
  • Finding full-on-glory can be tricky indeed--I'm glad this helped! – duhaime Sep 10 '18 at 18:50