当前位置: 首页 > 知识库问答 >
问题:

尝试从表单提交和触发器列表重新提交程序更新React上下文

诸葛砚
2023-03-14

我已经用这支钢笔玩了一段时间了,这是一种用各种钩子做的练习。我希望动态呈现上下文中的姓名列表,并在将新person对象发布到上下文数组后重新呈现该列表。

似乎我已经接近了,因为提交表单会记录更新的peopleNameList,但是上下文似乎没有正确更新,表单提交会使笔崩溃。我是错过了一些小的东西,还是错过了一个更大的作文问题?

const {createContext, useState, useEffect, useContext, useReducer} = React;

// https://stackoverflow.com/questions/55757761/handle-an-input-with-react-hooks

// https://upmostly.com/tutorials/how-to-use-the-usecontext-hook-in-react

var dataStore = {
  people: [
         {
            firstName: 'Jim',
            lastName: 'Smith',
            email: 'jims@email.com',
            age: 32,
            job: 'Engineer',
            transportation: 'car'
         },
         {
             firstName: 'Sarah',
             lastName: 'Alton',
             email: 'salton@email.com',
             age: 24,
             job: 'Programmer',
             transportation: 'bike'
         },
        {
             firstName: 'Leslie',
             lastName: 'Leeland',
             email: 'lleeland@woohoo.com',
             age: 24,
             job: 'Teacher',
             transportation: 'Scooter'
         }
    ]
};


// define that context takes an object and an update function
const PeopleContext = createContext();
const PeopleContextProvider = (props) => {
    // dataStore.people as default context state, with a reducer dispatch returned for use with useContext hook to add a new person from the form
    // note you cannot push to a state array because this mutates state directly
    // https://medium.com/javascript-in-plain-english/how-to-add-to-an-array-in-react-state-3d08ddb2e1dc
    const [peopleStore, addNewPerson] = useReducer((peopleStore, newPerson) =>
     peopleStore.concat(newPerson), dataStore.people);

    return(
        // Context Provider takes a value prop
        <PeopleContext.Provider value={[peopleStore, addNewPerson]}>
            {props.children}
        </PeopleContext.Provider>
    )
}

function RecentPeople(props) {
    // peopleStore equivalent to value prop of PeopleContext provider
    const [peopleStore, addNewPerson] = useContext(PeopleContext);

    const addToPeopleNameList = () => {
        let peopleNameList = [];
        _.map(peopleStore, (i) => {
            let name = `${i.firstName} ${i.lastName}`;
                peopleNameList.push(name);
            return peopleNameList;
        });
        console.log(`peopleNameList: ${peopleNameList}`);
        return(<>
                    {_.map(peopleNameList, (name, i) => <li key={i}>{name}</li>)}
                </>)
    };

    useEffect(() => addToPeopleNameList(), [peopleStore]);

    return(
        <>
        <h3>Recent People</h3>
        <ul>
            {addToPeopleNameList()}
        </ul>
        </>
    );
} // end RecentPeople

function Input(props) {
    let {inputId, value, handleChange } = props;
    let inputLabel = _.startCase(props.inputId);
    return(
        <div class="input-group">
            <label for={inputId}>{inputLabel}</label>
            <input id={inputId} value={value} name={inputId} onChange={handleChange} />
        </div>
    );
};

const inputFields = [ 'firstName', 'lastName', 'email', 'age', 'job', 'transportation' ]

const initialFormState = {
    firstName: '',
    lastName: '',
    email: '',
    age: null,
    job: '',
    transportation: ''
};

function NewUserForm(props) {
    // pass in the reducer function inline to concat existing and new state
    const [inputValues, setInputValues] = useReducer((state, newState) => ({...state, ...newState}), initialFormState);

    const [peopleStore, addNewPerson] = useContext(PeopleContext);

    function handleOnChange(event) {
     const {name, value} = event.target;
            // call the reducer update function, passing in existing formstate with state of current input
            setInputValues({...inputValues, [name]: value });
    }

    function handleSubmit(event) {
        event.preventDefault();
        addNewPerson(inputValues);
        console.log(peopleStore);
        setInputValues({}, {...initialFormState});
    }

    // don't pass event here
    function handleReset(props) {
        setInputValues({}, {...initialFormState});
    }

    return(
        <form id="new-user-form" onSubmit={handleSubmit}>
            {_.map(inputFields, (fieldName) => (<Input key={fieldName} type="text" name={fieldName} inputId={fieldName} handleChange={handleOnChange} />))}

            <button type="submit" value="submit">Add User</button>

            <button type="reset" style={{"marginLeft": "20px"}} onClick={handleReset}>Reset Form</button>
        </form>
    );
} // form


function App() {
    return(
        <PeopleContextProvider>
        <div id="main">
            <h1>Hello!</h1>
            <NewUserForm />
            <RecentPeople />
        </div>
        </PeopleContextProvider>
    );
};

ReactDOM.render(<App />, document.getElementById('App'));

共有1个答案

何楷
2023-03-14

看起来主要的罪魁祸首是使用效果不能直接返回呈现列表函数,并且需要将其包装在括号中以确定函数的范围。通过其他几个名称更改和小调整,更正后的笔在这里,现在显示上下文的调度函数被正确调用,列表组件监听更改并重新呈现列表。可能是一些优化,可以在那里只显示不同的项目。

https://codepen.io/smallreflection/pen/yLyLQge?editors=1011

useEffect(() => { renderPeopleNameList() }, [peopleStoreContext]);
 类似资料:
  • 审议本届会议: 这是一个在数据库中显示用户图像的图像,带有会话变量!然而,在我的网站中,我正在使用上传图像表单更改用户图片,用户图片正在更新,但旧图片将保留,直到我刷新页面…我希望避免刷新页面以解决此问题。。。。 请注意,我的目标是一个iframe,而不是重定向到我的操作。。。 这是我的上传表格,你可能不需要,但我会把它放在这里... 例如: 使现代化php示例 所以为了简单起见,我想在提交表单时

  • 我有一个正在写的剧本,需要一些帮助。 首先,我的脚本应该如何工作。 脚本:用户填写谷歌表单并点击提交。提交后,我的脚本运行并从google工作表中读取我在工作表中操作的一系列数据单元。然后将数据单元格格式化为字符串,并在表单的确认消息中提示。 现在问题来了。 问题:当我提交我对表格的回复时,从表格到表格的一切都很好。当我手动运行代码时,代码工作正常。当我提交表单响应时,事件历史记录会显示触发器并说

  • 问题内容: 每次尝试提交表单时,我都会收到此错误消息: CSRF令牌无效。请尝试重新提交表格 我的表单代码是这样的: 有任何想法吗? 问题答案: 您需要在表单中添加,即 截至目前,您的表单缺少CSRF令牌字段。如果您使用树枝形状表单函数来呈现表单,则将自动为您呈现CSRF令牌字段,但是您的代码显示您正在使用原始HTML来呈现表单,例如,因此您必须手动呈现该字段。 或者,只需在表单的结束标记之前添加

  • 问题内容: 我正在尝试使用React Hooks和表单更新UI。我设置了一个状态来监视表单上的值,当我单击“提交”时,我想将此值添加到数组(保持状态)并在UI上显示。我的问题是,当我提交值时,尽管它已添加到数组中(状态已更新),但UI仅在更改输入中的值时才更新。 我的组件如下: 您也可以在以下 网址看到此[不]工作: https //codesandbox.io/s/p3n327zn3q 是否有人

  • 获取Form变量 通过Action的如下方法可以获取变量: GetSlice GetString GetInt GetBool GetFloat GetFile GetForm 自动映射 通常我们通过http.Request.Form来获得从用户中请求到服务器端的数据,这些数据一般都是采用name,value的形式提交的。xweb默认支持自动将这些变量映射到Action的成员中,并且这种映射支持子

  • 问题内容: 我正在尝试创建一个将信息存储在组件的状态变量中的输入表单,然后在屏幕上输出该变量。我阅读了有关受控组件的文档,这就是我在这里尝试的内容。 我的主要问题是,当我单击提交时,正确的文本出现在屏幕上,但是随后整个页面都会刷新,我不确定为什么。从我在网上阅读的内容看,这似乎是一个解决方案,但我的理解是,我可以使用该组件或受控组件。 问题答案: 只需调用方法即可防止表单的默认行为