How to update props of React Component rendered using ReactDOM.render()

10,860

There is no magic at work here, you just need to re-render it.

Just wrapper your rendering into a function, eg:

function renderReactNavbar( tabs = [] ) {
  ReactDOM.render(
    <NavBar
        currencyTabs = { tabs }
    />, document.getElementById("navbar-root")
  );

}

and call it after you load / update your data.

Alternatively, you choose to load your data from inside react, which might be a better choice in the long run.

If you have internal state, this might be somewhat harder to handle. You could consider moving to a props only component (but since you don't share any relevant code of your react component, it is hard to say)

A small example of how it could look would be

// the render method, takes a component and props, and renders it to the page
function renderComponent( component, props ) {
  const target = document.querySelector('#container');
  ReactDOM.render( React.createElement( component, props ), target );
}

// gets the tabs from the input field, splits based on ,
function getTabsFromInput() {
  return document.querySelector('#tabs').value.split(',');
}

// small presentational component, shows the tabs and redirects selection changes through a callback
const Tabs = ({ tabs, selectedTab, onSelectionChanged }) => {
  return tabs && <div>{ tabs.map( (tab, key) => {
    return <h1 key={key} className={classNames( { 'active': key === selectedTab } ) } onClick={ () => onSelectionChanged( key ) }>{ tab }</h1>;
  } ) }</div>;
};

// some initiations
window.addEventListener('load', function() {
  // keep a local variable with the data
  let defaultProps = {
    onSelectionChanged: updateSelection,
    selectedTab: 0,
    tabs: getTabsFromInput()
  };

  // handles selection changes
  function updateSelection( newTab ) {
    defaultProps = {...defaultProps, selectedTab: newTab };
    renderComponent( Tabs, defaultProps );
  }

  // adds an event listener for click events to initiate tab changes
  document.querySelector('#updateTabs').addEventListener('click', function() {
    defaultProps = {...defaultProps, tabs: getTabsFromInput() };
    // render on update
    renderComponent( Tabs, defaultProps );
  });

  // initial render
  renderComponent( Tabs, defaultProps );
});
.active {
  background-color: blue;
}
<script id="react" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.js"></script>
<script id="react-dom" src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.js"></script>
<script id="classnames" src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.2.5/index.js"></script><div id="container"></div>
<input type="text" value="tab1,tab2" id="tabs" />
<button id="updateTabs" type="button">Update tabs</button>

Share:
10,860
rex
Author by

rex

Updated on June 17, 2022

Comments

  • rex
    rex almost 2 years

    I am trying to integrate react into my angularjs webapp.

    In my controller I create the component, which initially has array props that are empty. When the app is done initializing, I want to update the props again. Do I do this by calling ReactDOM.render() again or can I keep a reference to this instance and just do something like updateProps(newProps)?

    This is called from my controller:

    ReactDOM.render(
        <NavBar
            currencyTabs = {[]}
        />, document.getElementById("navbar-root")
    );
    

    And then when the data is done loading i need to update the currencyTabs with a full array ...

    I understand how react components props update from parent to child, but I don't quite get how I can do this from plain JS.

  • rex
    rex over 6 years
    Thank you -this is what I was wondering. Unfortunately loading the data inside the component is not an option at this time due to the nature and complexity of our app.
  • Icepickle
    Icepickle about 6 years
    It doesn't have state, it has props, at least from what we can see. If it has an internal state to manage the currencyTabs, that's another question. The lifecycle methods won't intervene here either, as this is directly rendered to a div element, react is simply used to render 1 single component)
  • Icepickle
    Icepickle about 6 years
    @rex Yeah, well then you have to make sure you reload at the correct times. So if you have a change in your data, just call the re-render. I am however unsure how internal state works in this case
  • John Hatton
    John Hatton over 4 years
    This answer is great, but I misunderstood it. So, note that might help someone else: ReactDom.render() does not give you a clean-slate; it just updates the component. So if your props did not change, it will not re-render. If you are fighting a system that isn't totally functional, and you have to do ReactDom.unmountComponetnAtNode() first (or introduce some other prop just for the sake of forcing an update). Have it working? OK good, now look for some way to remove that hack :-)
  • spritecodej
    spritecodej over 4 years
    I want to change just component and check the "componentWillRecieveProps". Then I apply some code in "componentWillRecieveProps" that is good working
  • ruffin
    ruffin about 2 years
    @JohnHatton's comment is important, afaict, but unfortunately contains a typo in unmountComponentAtNode! Here's unmountComponentAtNode in React's docs, and here's an answer from Dan Abramov saying why it's essential to use for [a subset of?] cases we're discussing, if I'm reading him right.