3

Imagine I have the following UI:

enter image description here

I click the input field and a modal opens where I can select between multiple options (essentially a fancily styled dropdown).

With normal Javascript I'd do something like:

<button id="show">Show</button>
<div id="popup">
    Please choose
    <button id="option1">1</button>
    <button id="option2">2</button>
    <button id="option3">3</button>
    <button id="option4">Little</button>
    <button id="option5">A lot</button>
    <button id="option6">A few</button>
</div>
<div id="result"></div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$('#popup').hide();
$('#show').click(function() {
    openPopup()
        .then(function(data) {
            $('#result').html("You pressed " + data)
            closePopup();
        })
})
function openPopup() {
    return new Promise(function(resolve, reject) {
        $('#popup').show();
        $('#option1').click(function() { resolve('"1"') })
        $('#option2').click(function() { resolve('"2"') })
        $('#option3').click(function() { resolve('"3"') })
        $('#option4').click(function() { resolve('"Little"') })
        $('#option5').click(function() { resolve('"A lot"') })
        $('#option6').click(function() { resolve('"A few"') })
    });
}
function closePopup() {
    $('#popup').hide();
}
</script>

Current React code:

My react code so far is (with boring parts stripped away):

function Modal(){
    return (
        <div>
            <div>
                <UnitBlock name="1" />
                <UnitBlock name="2" />
                <UnitBlock name="3" />
                <UnitBlock name="4" />
                <UnitBlock name="5" />
            </div>
            <div>
                <UnitBlock name="Little" />
                <UnitBlock name="A lot" />
                <UnitBlock name="A few" />
            </div>
        </div>
        )
}

function UnitBlock(props) {
  return <div className="UnitBlock">{props.name}</div>
}

function FakeInputField(props){
    return <div className="FakeInputField">{props.name}</div>   
}

function example(){
    return(
        <div>
            <FakeInputField name="Amount"/>
            <Modal/>
        </div>
    )
}

So my basic question is: How could I return a value to the (fake) input field by clicking on one of the buttons in the modal?

Like in the example with the promises I tried to create something simple, like "Interacting with the input field opens the modal, and then the button you click sends its information to the input field".

st_phan
  • 715
  • 9
  • 23
  • You can add callback to your Modal, pass it in props and call it after click on button – Sabik May 29 '18 at 13:08
  • 1
    Make sure you read [Lifting State Up](https://reactjs.org/docs/lifting-state-up.html) and [Thinking in React](https://reactjs.org/docs/thinking-in-react.html) in the docs - they explain the idiomatic way of communicating between components (spoilers - it's exactly what Sabik suggested!). – Joe Clay May 29 '18 at 13:10
  • I read through both sections in the doc earlier, but didn't understand everything. It's becoming to get clearer now though ... thanks for pointing out. – st_phan May 29 '18 at 13:46

2 Answers2

2

I ended up using:

class Parent extends React.Component{
    useDataFromChild = (value) => {
        console.log(value)
    }

    render() {
         return (
                <div>
                    <Child name="Option: Little" onReceiveData={this.useDataFromChild}/>
                    <Child name="Option: Many" onReceiveData={this.useDataFromChild}/>
                </div>
        )
     }
}

class Child extends React.Component {
    sendData = () => {
        this.props.onReceiveData(this.props);            
    }

    render() {
        return (
            <div >
                <div onClick={this.sendData}>{this.props.name}</div>
            </div>            
        );
    }
}

ReactDOM.render(<Parent/>, document.getElementById('root'));

But apparently React Redux is the way to go with these problems.

st_phan
  • 715
  • 9
  • 23
0

I think that this is a similar to: React js onClick can't pass value to method

However the easiest solution is:

class Modal extends React.Component { 
  resolve = (val) => { console.log(val); } 

  render() { 
    return ( 
      <div> 
        <div> 
          <UnitBlock name="1" onClick={() => this.resolve(1)}/> 
          <UnitBlock name="2" onClick={() => this.resolve(2)}/> 
        </div> 
      </div>)  
  } 

} 

function UnitBlock(props) { 
  return <div className="UnitBlock">{props.name}</div> 
}

Better Solution

https://codesandbox.io/s/p9lk4ooxxq

class UnitBlock extends React.Component { 
  resolve = (val) => { console.log(val); } 

  render() { 
    return <div className="UnitBlock" onClick={
      () => this.resolve(this.props.name)}>{this.props.name}</div>
  }
}

function UnitBlock(props) { 
    return ( 
      <div> 
        <div> 
          <UnitBlock name="1"}/> 
          <UnitBlock name="2"}/> 
        </div> 
      </div>)  
  } 

} 
Luca
  • 105
  • 1
  • 1
  • 7
  • I added the onClick to my UnitBlock and changed Component to React.Component and now it works perfectly: `class Modal extends React.Component { resolve = (val) => { console.log(val); } render() { return (
    this.resolve(1)}/> this.resolve(2)}/>
    ) } } function UnitBlock(props) { return
    {props.name}
    }` Do you mind adding it to your answer?
    – st_phan May 29 '18 at 13:45
  • I don't think that is required to add onClick to UnitBlock – Luca May 29 '18 at 13:56
  • When I used a div instead of the component Unitblock it worked perfectly (your solution). But with Unitblock the click listener just didn't fire until I added `onClick={props.onClick}` – st_phan May 29 '18 at 20:23
  • Please check the link that I've posted in the solution and as you see seems to work fine for me: https://codesandbox.io/s/p9lk4ooxxq – Luca May 30 '18 at 07:52
  • Your solution works, but I need to access the data from the child in parent: I ended up using this solution https://codesandbox.io/s/0q93yy5vkl – st_phan May 30 '18 at 09:53
  • Now i get what you want to do. Yes I agree with you. I don't know the complexity of your project, but have a look to `Redux` https://redux.js.org/basics/usage-with-react Is helping a to pass parameters and functions to inner components – Luca May 30 '18 at 09:58
  • Sorry that it wasn't clear. I am still not sure how all the parts interplay ... But I think it's starting to make more sense. Thank you so much for your help – it really pushed me into the right direction! – st_phan May 30 '18 at 10:25