E
E
Egor Astreiko2019-06-26 21:00:16
React
Egor Astreiko, 2019-06-26 21:00:16

React app, is it possible to create such a component?

Hello everyone, I came across a stupid desire, namely:
Is it possible in react to make the component return the changed variable?

Has a parent component

class Parent extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            value1: "",
            value2: "",
            value3: "",
        };

        this.handleOnClick = this.handleOnClick.bind(this);

        this.elements = [
            {
                className: "parent__input parent__input--1",
                type: "text",
                val: this.state.value1,
                placeholder: "placeholder1"
            },
            {
                className: "parent__input parent__input--1",
                type: "text",
                val: this.state.value2,
                placeholder: "placeholder2"
            },
            {
                className: "parent__input parent__input--1",
                type: "text",
                val: this.state.value3,
                placeholder: "placeholder3"
            },
        ]
    }

    handleOnClick() {
        console.log(this.state.value1, this.state.value2, this.state.value3);
    }

    render() {
        return (
            <>
                {this.elements.map((element, index) => {
                    return (<Child key={index} className={element.className} type={element.type} value={element.val}
                                   placeholder={element.placeholder}/>)
                })}

                <div style={{marginTop: "10px"}}>
                    <span onClick={this.handleOnClick}>Кнопка</span>
                </div>
            </>
        )
    }
}


There is a child component

const Child = ({className, type, value, placeholder}) => {

    const [innerValue, setInnerValue] = useState(value);

    const handleOnChange = (e) => {
        setInnerValue(e.target.value)
    };

    return (
        <div className={"input"}>
            <input onChange={handleOnChange} className={"input__field" + (className ? ` ${className}` : '')} type={type ? type : 'text'}
                   value={innerValue}/>
            {placeholder && <span className={"input__placeholder"}>{placeholder}</span>}
        </div>
    )
};


this.state - emits data from the reducer

this.state = {
            value1: "1",
            value2: "2",
            value3: "3",
        };


The problem is, now after filling in the fields and clicking on the button in the parent component, I, as expected, will not receive the new values ​​​​of the variables (value1, value2, value3), is it possible to somehow make the child component change the variable that I I pass it through the parameters?
Now I use, it seems to me, a rake:
I pass a function from the parent that takes a new string as a parameter and call it during the onChange event (with this approach, I don’t know which variable this changes), you can pass an indicator to this variable in the role of id to the child component and pass it to the parent function as the second parameter, but then you need to somehow enumerate each variable, and this is not convenient ...

I want to achieve this result:
I have an array of variables from the reducer that are responsible for the input fields, I create components using map, pass these variables from the reducer to them, when filled, these variables change, and then by clicking on the button I send these variables back to reducer
Thanks in advance.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
A
Anton Spirin, 2019-06-27
@Egor1324

1 Don't store form state in a reducer. In most cases this is not necessary.
2. Remove the internal state of value from Input. Now you get two sources of truth, but what they are for you, I believe, you yourself do not understand.
3. Try not to break native interfaces unnecessarily.
Your code:
How you should have done it:
4. Optimize the repetitive code in handleParentOnChange. And instead of id, use the name attribute.

handleParentOnChange(e) {
  const { name, value } = e.target;
  this.setState({
    [name]: value,
  });
}

R
Robur, 2019-06-26
@Robur

What you are doing is right. pass a variable and onChange, change this variable in it, store everything in the parent state. If there are problems with changing the necessary variable in onChange - this is solvable - this is what you need to solve.
Since you want to do it, it’s also possible, but it won’t even be a rake, but a very bad code, so as not to produce the amount of shit code on the planet, I won’t explain how.

M
Mikhail Osher, 2019-06-26
@miraage

https://react-use-form-state.now.sh/

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question