• Two-way binding will make your React code better
  • Originally written by Mikhail Boutylin
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: tong – h
  • Proofread by: NIA3Y

Two-way binding will make your React code better

Bidirectional binding allows synchronization between two entities, such as the data layer and the view layer of the application. React provides an API for one-way binding right out of the box. When we want to modify state, we need to explicitly call the update callback:

const UserName = ({ name, onChange }) = > {
	return <input onChange={onChange} value={name} />
}
const App = () = > {
	const [user, setUser] = useState({ name: "" })
	return <UserName name={user.name} onChange={(e)= > setUser({ name: e.target.value })} />
}
Copy the code

This provides a channel for updating child elements. When the state of the root node is updated, the change is propagated to the child elements. This makes application data flow clear and predictable, but increases the amount of code. To match two-way binding with React’s update philosophy, I created the Mlyn library. The main paradigm is that each part of state is read and write. When you write state, this change will bubble up to the root state and cause it to update:

// The trailing $symbol indicates that the value is monitored
const UserName = ({ name$ }) = > {
	return <Mlyn.Input bindValue={name$} />
}
const App = () = > {
	const user$ = useSubject({ name: "" })
	return <UserName name$={user$.name} />
}
Copy the code

As such, the engine updates the state in the same way as in the normal React example above.

Bidirectional binding is not limited to interacting with the UI, you can easily bind your values to localStorage. You have a hook that accepts part of the Mlyn state and the target localStorage key:

const useSyncronize = (subject$, key) = > {
	useEffect(() = > {
		// If state exists, write to it
		if (localStorage[key]) {
			subject$(JSON.parse(localstorage[key]))
		}
	}, [])
	useMlynEffect(() = > {
		// update localStorage
		localStorage[key] = JSoN.stringify(subject$())
	})
}
Copy the code

Now you can easily bind the user name to localStorage:

useSyncronize(user$.name, "userName");
Copy the code

Note that you do not need to create or pass any callback functions to update the value for it to take effect. Another use case is when you want to make changes to state undoable or rewritable, you just need to pass the state to the correct history management hook again.

const history = useHistory(state$.name);
Copy the code

The history object contains an API jumpTo jumpTo any phase of state, but this is a two-way binding with a bit of customization. Whenever state is updated, the new snapshot is pushed into the history:

When you select a history state, the state will be overridden back to state:

Again, notice that we didn’t write a custom boilerplate for the state update, just concatenated historical snapshots. Check out this History management code sandbox for the TodoMVC application:

For more bidirectional binding and Mlyn examples, visit React – Mlyn.

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.