简体   繁体   中英

React + Foundation - Render Modal with different props on click

I am working off of course example "Todo" app by trying to incorporate Foundation Modal. I have three components in question: TodoList.jsx, Todo.jsx, and TodoModal.jsx.

What I want is a link to show up below each todo in todoList to popup a modal with todo contents. My problem: I can launch the Modal, but same Modal pops up regardless of which todo link I'm clicking. It seems like I am not able to update the props in TodoModal.jsx and may be component lifecycle in React, but I really need help proceeding ahead. I just took an online React course, so I am still new. Any help is greatly appreciated!

Below are TodoList.jsx (which sends todo data to TodoModal.jsx and Todo.jsx) and TodoModal.jsx.

TodoList.jsx

var React = require('react');
var {connect} = require('react-redux');
import Todo from 'Todo';
var TodoAPI = require('TodoAPI');

import TodoModal from 'TodoModal';

export var TodoList = React.createClass({
    render: function () {
      var {todos, showCompleted, searchText} = this.props;
      var renderTodos = () => {
      var filteredTodos = TodoAPI.filterTodos(todos, showCompleted, searchText);

      if (filteredTodos.length === 0) {
        return (  <p className="container__message">Nothing To Do</p>  );
      }

      return filteredTodos.map((todo) => {
        return (
          <div>
            <Todo key={todo.id} {...todo}/>
            <div>
              <a data-open="item-modal">
                  {todo.id}
              </a>
            <TodoModal todo={todo}/>
            </div>
          </div>
        );
      });
    };

    return (
      <div>
        {renderTodos()}
      </div>
    )
  }
});    
export default connect((state) => {return state })(TodoList);

TodoModal.jsx:

var React = require('react');
var ReactDOM = require('react-dom');
var ReactDOMServer = require('react-dom/server');

var TodoModal = React.createClass({
  componentDidMount: function () {
    var modalMarkup = (
      <div id="item-modal" className="reveal tiny text-center" data-reveal="">
        <h4>{this.props.todo.text}</h4>
        <p>{this.props.todo.id}</p>
        <p>
          <button className="button hollow" data-close="">
            Okay
          </button>
        </p>
      </div>
    );

    var $modal = $(ReactDOMServer.renderToString(modalMarkup));
    $(ReactDOM.findDOMNode(this)).html($modal);
    var modal = new Foundation.Reveal($("#item-modal"));
  },

  componentWillReceiveProps: function (newProps) {
    console.log(newProps)
  },

  render: function () {  
    return (<div> </div>);
  }
});
module.exports = TodoModal;

I'm not familiar with Foundation Modal but I believe the problem is with when you're setting up the modalMarkup component.

According to the lifecycle of React components, componentDidMount is only called once when the component is loaded. When you get new props via componentWillRecieveProps , the componentDidMount function is NOT re-invoked and therefore your modal is not referencing the new props.

Instead try to create the modal in both (if you can) componentDidMount and componentWillReceiveProps to handle the new props, maybe via a createModal(props) function which you can pass in the relevant set of props.

I wish I could give you more information on how to create the modal but as I said I'm not familiar with Foundation Modal .

You can read more about the lifecyle of the components here: Component Specs and Lifecycle

Updated in response to your comment

To pass new props to your TodoModal component you simply need to change the value you're passing to the TodoModal component's todo property. For example lets assume you have a component called CompA which is rendering CompB and CompB requires a property item . CompA 's render may look like this:

CompA

render: function () {
    return (<CompB item={this.props.myItem}/>);
}

But now lets say that CompB can be provided new property values and defines the componentWillRecieveProps function. The current setup would ONLY pass a prop to CompB if CompA 's property myItem was changed. You could technically do this but you could also do something like the following:

CompA

getInitialState: function () {
    return {
        item: this.props.myItem
    };
},

render: function() {
    // Use the state as the value for CompB's property
    // Then changing the state will invoke CompB's componentWillReceiveProps function
    return (<CompB item={this.state.item}/>);
}

Now in this case change CompA 's state will the new value to be passed to CompB and then CompB would receive it as a newly received props. You can make the state change be invoked by some event like a click, hover, whatever and you should have what you were asking about.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM