React programming pattern
I'd say, if it's the Presentation and Container Components pattern as described by Dan Abramov, then yes, you've pretty effectively nailed it. (Though Dan no longer advocates this pattern!!)
Suggestions/Review
AddForm
items prop is really the text state in the parent component, it doesn't need the entire state object. (If it does then name it more accurately!) What's used is just the input value, so value is a better descriptor.
export const AddForm = ({ value, onSubmit, onChange }) =&gt; {
  console.log(value);
  return (
    &lt;div className=&quot;add-item-form&quot;&gt;
      &lt;form onSubmit={e =&gt; onSubmit(e)}&gt;
        &lt;label htmlFor=&quot;name&quot;&gt;Add new todo:&lt;/label&gt;
        &lt;input
          type=&quot;text&quot;
          id=&quot;name&quot;
          onChange={e =&gt; onChange(e)}
          value={value}
        /&gt;
        &lt;button
          className=&quot;btn waves-effect waves-light&quot;
          type=&quot;submit&quot;
          name=&quot;action&quot;
        &gt;
          Add item
        &lt;/button&gt;
      &lt;/form&gt;
    &lt;/div&gt;
  );
};

Usage: &lt;AddForm value={this.state.text}  ...  /&gt;
TodosContainer
The handlers are all arrow functions, they already have the this of the class bound to them, so there isn't need to bind them in a constructor. In fact, if all the constructor is doing is setting the initial state, then you don't really need the constructor either as you can simply set initial state with a state instance variable.
Instead of
constructor(props) {
  super(props);
  this.state = { items: [], text: '' };
  this.handleChange = this.handleChange.bind(this);
  this.handleSubmit = this.handleSubmit.bind(this);
  this.removeItem = this.removeItem.bind(this);
}

Simply
state = { items: [], text: '' };

State updates
When any next state depends upon current state, like incrementing counters, or adding values to arrays, you should get into the habit of using functional state updates, and also not referencing this.state within the state update.
State and Lifecycle
setState
handleSubmit can be improved
handleSubmit = (e) =&gt; {
  e.preventDefault();
  const newItem = {
    text: this.state.text,
    id: Date.now(),
  };
  if (this.state.text) { // &lt;-- if text is truthy, i.e. non-empty string
    this.setState(prevState =&gt; ({
      items: prevState.items.concat(newItem), 
    }));
  }
}

State updates are also asynchronous, so don't try to console.log it after requesting the state update. Use a component lifecycle like componentDidUpdate to log state after the update (or for class-based components, you can use the setState 2nd parameter callback function, but for simplicity sake stick to the lifecycle functions.).
removeItem handler can be improved
removeItem = (id) =&gt; {
  this.setState(prevState =&gt; ({
    items: prevState.items.filter(item =&gt; item.id !== id),
  }));
}