Pass state between components without hierarchy

Asked

Viewed 85 times

2

I’m making a whole app list, and I’d like to have the Edit button appear in the field where I add my new item. But the action of the button and the state are sibling components.

Addtodo (as I pass the state of Addtodo to Todo ?)

import React, { Component } from "react";

export default class AddTodo extends Component {
  state = {
    content: ""
  };
  handleChange = e => {
    this.setState({ content: e.target.value });
  };
  handleSubmit = e => {
    e.preventDefault();
    this.props.addTodo(this.state);
    this.setState({ content: "" });
  };
  // Como passar o estado dessa função ?
  render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <label class="blue-text">Add new todo</label>
          <input
            type="text"
            onChange={this.handleChange}
            value={this.state.content}
          />
        </form>
      </div>
    );
  }
}

All

import React from "react";
import "./style.css";

const Todos = ({ todos, deleteTodo }) => {
  const todoList = todos.length ? (
    todos.map(todo => {
      return (
        <div className="collection-item" key={todo.id}>
          <span
            onClick={() => {
              deleteTodo(todo.id);
            }}
          >
            {todo.content}
          </span>
          <button 
          class="btn-small orange lighten-1 right"
           id="btnEdit"
           onClick={() => {editTodo(todo.content)}}
           >
            <i class="material-icons">edit</i>
          </button>
        </div>
      );
    })
  ) : (
    <p className="center">Nothing todo, yay</p>
  );
  return <div className="todos collection">{todoList}</div>;
};
export default Todos;

App

import React, { Component } from "react";
import Todos from "./Todos";
import AddTodo from "./AddTodo";

export default class App extends Component {
  state = {
    todos: [
      { id: 1, content: "learning Redux" },
      { id: 2, content: "buy some milk" },
      { id: 3, content: "play Mario kart" }
    ]
  };

  deleteTodo = id => {
    const todos = this.state.todos.filter(todo => {
      return todo.id !== id;
    });
    this.setState({ todos });
  };
  addTodo = todo => {
    todo.id = Math.random();
    const todoss = [...this.state.todos, todo];
    this.setState({ todos: todoss });
  };
  
  render() {
    return (
      <div className="todo-app container">
        <h1 className="center blue-text">Todo list</h1>
        <Todos todos={this.state.todos} deleteTodo={this.deleteTodo} />
        <AddTodo addTodo={this.addTodo} />
      </div>
    );
  }
}

  • You can only pass props from parent components to child components, directly between siblings is not possible, in which case you would have to go from one child, to father and father to another child.

  • True, I’m putting in the state of the App an array to receive the status of the child, since App is the parent, now we need to do a function that passes this state to Addtodo child, because this Addtodo is an insert capo, the idea is to put the text right there. Got confused ?

  • Study Redux or Context of Reactjs

  • 1

    No, that’s the idea. I think there’s a way to get through it, but using Hooks, I think Usecontext does this, it goes straight to any component without taking into consideration it was hierarchy. But since you are using Class Components I believe that only so, from father to son.

  • 1

    You can control the state in the father and pass a function of criarTodo for a child and the listaDeTodos for the other son. Worth reading When to use context? and Before you use context.

  • I made an example with Context but it’s with React Hooks

Show 1 more comment

1 answer

0

This is a way to program a link between components where they share the same data and when the button increments or decreases the action is clicked to program the state variable count in those with this variable of Context, example:

const GlobalContext = React.createContext();
function GlobalProvider({children}) {
  const [count, setCount] = React.useState(0);
  const handleIncrement = () => setCount(count + 1);
  const handleDecrement = () => setCount(count - 1);
  return (
    <GlobalContext.Provider value={{count, handleIncrement, handleDecrement}}>
      {children}
    </GlobalContext.Provider>
  )
}

function Score() {
  const { count, handleIncrement, handleDecrement  } = React.useContext(GlobalContext);
  return (<div>
    <div>{count}</div>
    <button onClick={handleIncrement}>Incremento</button>
    <button onClick={handleDecrement}>Decremento</button>
  </div>);
}

function Actions() {
  const { count } = React.useContext(GlobalContext);
  return (<div>{count}</div>);
}

function App() {  
  return (
    <GlobalProvider>
      <Score />
      <Actions/>
    </GlobalProvider>
  )
}

ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

in this example code is created a context with React.createContext();and right in the next line a function to facilitate the creation of your Provider and finally within the <App /> involved two components that shared functions and data from that Provider.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.